1 from Plugins.Plugin import PluginDescriptor
2 from Screens.Console import Console
3 from Screens.ChoiceBox import ChoiceBox
4 from Screens.MessageBox import MessageBox
5 from Screens.Screen import Screen
6 from Screens.Ipkg import Ipkg
7 from Components.ActionMap import ActionMap, NumberActionMap
8 from Components.Input import Input
9 from Components.Ipkg import IpkgComponent
10 from Components.Label import Label
11 from Components.ScrollLabel import ScrollLabel
12 from Components.Pixmap import Pixmap
13 from Components.MenuList import MenuList
14 from Components.Sources.List import List
15 from Components.Slider import Slider
16 from Components.Harddisk import harddiskmanager
17 from Components.config import config,getConfigListEntry, ConfigSubsection, ConfigText, ConfigLocations
18 from Components.Console import Console
19 from Components.MultiContent import MultiContentEntryText, MultiContentEntryPixmapAlphaTest
20 from Components.SelectionList import SelectionList
21 from Components.PluginComponent import plugins
22 from Components.About import about
23 from Components.DreamInfoHandler import DreamInfoHandler
24 from Components.Language import language
25 from Components.AVSwitch import AVSwitch
26 from Tools.Directories import pathExists, fileExists, resolveFilename, SCOPE_PLUGINS, SCOPE_SKIN_IMAGE, SCOPE_METADIR
27 from Tools.LoadPixmap import LoadPixmap
28 from enigma import eTimer, quitMainloop, RT_HALIGN_LEFT, RT_VALIGN_CENTER, eListboxPythonMultiContent, eListbox, gFont, getDesktop, ePicLoad
29 from cPickle import dump, load
30 from os import path as os_path, system as os_system, unlink, stat, mkdir, popen, makedirs, listdir, access, rename, remove, W_OK, R_OK, F_OK
31 from time import time, gmtime, strftime, localtime
32 from stat import ST_MTIME
33 from datetime import date
34 from twisted.web import client
35 from twisted.internet import reactor
37 from ImageWizard import ImageWizard
38 from BackupRestore import BackupSelection, RestoreMenu, BackupScreen, RestoreScreen, getBackupPath, getBackupFilename
40 config.plugins.configurationbackup = ConfigSubsection()
41 config.plugins.configurationbackup.backuplocation = ConfigText(default = '/media/hdd/', visible_width = 50, fixed_size = False)
42 config.plugins.configurationbackup.backupdirs = ConfigLocations(default=['/etc/enigma2/', '/etc/network/interfaces', '/etc/wpa_supplicant.conf', '/etc/resolv.conf', '/etc/default_gw', '/etc/hostname'])
44 def write_cache(cache_file, cache_data):
46 if not os_path.isdir( os_path.dirname(cache_file) ):
48 mkdir( os_path.dirname(cache_file) )
50 print os_path.dirname(cache_file), 'is a file'
51 fd = open(cache_file, 'w')
52 dump(cache_data, fd, -1)
55 def valid_cache(cache_file, cache_ttl):
56 #See if the cache file exists and is still living
58 mtime = stat(cache_file)[ST_MTIME]
62 if (curr_time - mtime) > cache_ttl:
67 def load_cache(cache_file):
75 class UpdatePluginMenu(Screen):
77 <screen name="UpdatePluginMenu" position="80,130" size="560,330" title="Softwaremanager..." >
78 <ePixmap pixmap="skin_default/border_menu_300.png" position="5,10" zPosition="1" size="300,300" transparent="1" alphatest="on" />
79 <widget source="menu" render="Listbox" position="10,20" size="290,260" scrollbarMode="showOnDemand">
80 <convert type="TemplatedMultiContent">
82 MultiContentEntryText(pos = (2, 2), size = (290, 22), flags = RT_HALIGN_LEFT, text = 1), # index 0 is the MenuText,
84 "fonts": [gFont("Regular", 20)],
89 <widget source="menu" render="Listbox" position="310,10" size="240,300" scrollbarMode="showNever" selectionDisabled="1">
90 <convert type="TemplatedMultiContent">
92 MultiContentEntryText(pos = (2, 2), size = (240, 300), flags = RT_HALIGN_CENTER|RT_VALIGN_CENTER|RT_WRAP, text = 2), # index 2 is the Description,
94 "fonts": [gFont("Regular", 20)],
101 def __init__(self, session, args = 0):
102 Screen.__init__(self, session)
103 self.skin_path = plugin_path
106 self.oktext = _("\nPress OK on your remote control to continue.")
107 self.backupdirs = ' '.join( config.plugins.configurationbackup.backupdirs.value )
109 self.list.append(("software-update", _("Software update"), _("\nOnline update of your Dreambox software." ) + self.oktext) )
110 #self.list.append(("install-plugins", _("Install extensions"), _("\nInstall new Extensions or Plugins to your dreambox" ) + self.oktext) )
111 self.list.append(("software-restore", _("Software restore"), _("\nRestore your Dreambox with a new firmware." ) + self.oktext))
112 self.list.append(("system-backup", _("Backup system settings"), _("\nBackup your Dreambox settings." ) + self.oktext))
113 self.list.append(("system-restore",_("Restore system settings"), _("\nRestore your Dreambox settings." ) + self.oktext))
114 self.list.append(("ipkg-install", _("Install local IPKG"), _("\nScan for local packages and install them." ) + self.oktext))
115 if config.usage.setup_level.index >= 2: # expert+
116 self.list.append(("advanced", _("Advanced Options"), _("\nAdvanced options and settings." ) + self.oktext))
118 self.list.append(("advancedrestore", _("Advanced restore"), _("\nRestore your backups by date." ) + self.oktext))
119 self.list.append(("backuplocation", _("Choose backup location"), _("\nSelect your backup device.\nCurrent device: " ) + config.plugins.configurationbackup.backuplocation.value + self.oktext ))
120 self.list.append(("backupfiles", _("Choose backup files"), _("Select files for backup. Currently selected:\n" ) + self.backupdirs + self.oktext))
121 if config.usage.setup_level.index >= 2: # expert+
122 self.list.append(("ipkg-manager", _("Packet management"), _("\nView, install and remove available or installed packages." ) + self.oktext))
123 self.list.append(("ipkg-source",_("Choose upgrade source"), _("\nEdit the upgrade source address." ) + self.oktext))
125 self["menu"] = List(self.list)
127 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
134 self.onLayoutFinish.append(self.layoutFinished)
135 self.backuppath = getBackupPath()
136 self.backupfile = getBackupFilename()
137 self.fullbackupfilename = self.backuppath + "/" + self.backupfile
138 self.onShown.append(self.setWindowTitle)
140 def layoutFinished(self):
142 self["menu"].index = idx
144 def setWindowTitle(self):
145 self.setTitle(_("Software manager..."))
148 current = self["menu"].getCurrent()
152 if (current == "software-update"):
153 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to update your Dreambox?")+"\n"+_("\nAfter pressing OK, please wait!"))
154 elif (current == "software-restore"):
155 self.session.open(ImageWizard)
156 elif (current == "install-plugins"):
157 self.session.open(PluginManager, self.skin_path)
158 elif (current == "system-backup"):
159 self.session.openWithCallback(self.backupDone,BackupScreen, runBackup = True)
160 elif (current == "system-restore"):
161 if os_path.exists(self.fullbackupfilename):
162 self.session.openWithCallback(self.startRestore, MessageBox, _("Are you sure you want to restore your Enigma2 backup?\nEnigma2 will restart after the restore"))
164 self.session.open(MessageBox, _("Sorry no backups found!"), MessageBox.TYPE_INFO)
165 elif (current == "ipkg-install"):
167 from Plugins.Extensions.MediaScanner.plugin import main
170 self.session.open(MessageBox, _("Sorry MediaScanner is not installed!"), MessageBox.TYPE_INFO)
171 elif (current == "advanced"):
172 self.session.open(UpdatePluginMenu, 1)
174 if (current == "ipkg-manager"):
175 self.session.open(PacketManager, self.skin_path)
176 elif (current == "backuplocation"):
177 parts = [ (r.description, r.mountpoint, self.session) for r in harddiskmanager.getMountedPartitions(onlyhotplug = False)]
179 if not access(x[1], F_OK|R_OK|W_OK) or x[1] == '/':
182 if x[1].startswith('/autofs/'):
185 self.session.openWithCallback(self.backuplocation_choosen, ChoiceBox, title = _("Please select medium to use as backup location"), list = parts)
186 elif (current == "backupfiles"):
187 self.session.openWithCallback(self.backupfiles_choosen,BackupSelection)
188 elif (current == "advancedrestore"):
189 self.session.open(RestoreMenu, self.skin_path)
190 elif (current == "ipkg-source"):
191 self.session.open(IPKGMenu, self.skin_path)
193 def backupfiles_choosen(self, ret):
194 self.backupdirs = ' '.join( config.plugins.configurationbackup.backupdirs.value )
196 def backuplocation_choosen(self, option):
197 if option is not None:
198 config.plugins.configurationbackup.backuplocation.value = str(option[1])
199 config.plugins.configurationbackup.backuplocation.save()
200 config.plugins.configurationbackup.save()
202 self.createBackupfolders()
204 def runUpgrade(self, result):
206 self.session.open(UpdatePlugin, self.skin_path)
208 def createBackupfolders(self):
209 print "Creating backup folder if not already there..."
210 self.backuppath = getBackupPath()
212 if (os_path.exists(self.backuppath) == False):
213 makedirs(self.backuppath)
215 self.session.open(MessageBox, _("Sorry, your backup destination is not writeable.\n\nPlease choose another one."), MessageBox.TYPE_INFO)
217 def backupDone(self,retval = None):
219 self.session.open(MessageBox, _("Backup done."), MessageBox.TYPE_INFO)
221 self.session.open(MessageBox, _("Backup failed."), MessageBox.TYPE_INFO)
223 def startRestore(self, ret = False):
226 self.session.open(RestoreScreen, runRestore = True)
228 class IPKGMenu(Screen):
230 <screen name="IPKGMenu" position="135,144" size="450,320" title="Select IPKG source......" >
231 <widget name="filelist" position="10,10" size="430,240" scrollbarMode="showOnDemand" />
232 <ePixmap pixmap="skin_default/buttons/red.png" position="10,280" zPosition="2" size="140,40" transparent="1" alphatest="on" />
233 <widget name="closetext" position="20,290" size="140,21" zPosition="10" font="Regular;21" transparent="1" />
234 <ePixmap pixmap="skin_default/buttons/green.png" position="160,280" zPosition="2" size="140,40" transparent="1" alphatest="on" />
235 <widget name="edittext" position="170,290" size="300,21" zPosition="10" font="Regular;21" transparent="1" />
238 def __init__(self, session, plugin_path):
239 Screen.__init__(self, session)
240 self.skin_path = plugin_path
242 self["closetext"] = Label(_("Close"))
243 self["edittext"] = Label(_("Edit"))
252 self["actions"] = NumberActionMap(["SetupActions"],
255 "cancel": self.keyCancel
258 self["shortcuts"] = ActionMap(["ShortcutActions"],
260 "red": self.keyCancel,
264 self["filelist"] = MenuList(self.flist)
266 self.onLayoutFinish.append(self.layoutFinished)
268 def layoutFinished(self):
269 self.setWindowTitle()
271 def setWindowTitle(self):
272 self.setTitle(_("Select IPKG source to edit..."))
277 self.path = '/etc/ipkg/'
278 if (os_path.exists(self.path) == False):
281 for file in listdir(self.path):
282 if (file.endswith(".conf")):
283 if file != 'arch.conf':
284 self.flist.append((file))
286 self["filelist"].l.setList(self.flist)
289 if (self.exe == False) and (self.entry == True):
290 self.sel = self["filelist"].getCurrent()
291 self.val = self.path + self.sel
292 self.session.open(IPKGSource, self.val)
301 class IPKGSource(Screen):
303 <screen name="IPKGSource" position="100,100" size="550,80" title="IPKG source" >
304 <widget name="text" position="10,10" size="530,25" font="Regular;20" backgroundColor="background" foregroundColor="#cccccc" />
305 <ePixmap pixmap="skin_default/buttons/red.png" position="10,40" zPosition="2" size="140,40" transparent="1" alphatest="on" />
306 <widget name="closetext" position="20,50" size="140,21" zPosition="10" font="Regular;21" transparent="1" />
307 <ePixmap pixmap="skin_default/buttons/green.png" position="160,40" zPosition="2" size="140,40" transparent="1" alphatest="on" />
308 <widget name="edittext" position="170,50" size="300,21" zPosition="10" font="Regular;21" transparent="1" />
311 def __init__(self, session, configfile = None):
312 Screen.__init__(self, session)
313 self.session = session
314 self.configfile = configfile
318 fp = file(configfile, 'r')
319 sources = fp.readlines()
327 x= int(desk.size().width())
328 y= int(desk.size().height())
329 #print "[IPKGSource] mainscreen: current desktop size: %dx%d" % (x,y)
331 self["closetext"] = Label(_("Cancel"))
332 self["edittext"] = Label(_("Save"))
335 self["text"] = Input(text, maxSize=False, type=Input.TEXT)
337 self["text"] = Input(text, maxSize=False, visible_width = 55, type=Input.TEXT)
339 self["actions"] = NumberActionMap(["WizardActions", "InputActions", "TextEntryActions", "KeyboardInputActions","ShortcutActions"],
345 "left": self.keyLeft,
346 "right": self.keyRight,
347 "home": self.keyHome,
349 "deleteForward": self.keyDeleteForward,
350 "deleteBackward": self.keyDeleteBackward,
351 "1": self.keyNumberGlobal,
352 "2": self.keyNumberGlobal,
353 "3": self.keyNumberGlobal,
354 "4": self.keyNumberGlobal,
355 "5": self.keyNumberGlobal,
356 "6": self.keyNumberGlobal,
357 "7": self.keyNumberGlobal,
358 "8": self.keyNumberGlobal,
359 "9": self.keyNumberGlobal,
360 "0": self.keyNumberGlobal
363 self.onLayoutFinish.append(self.layoutFinished)
365 def layoutFinished(self):
366 self.setWindowTitle()
369 def setWindowTitle(self):
370 self.setTitle(_("Edit IPKG source URL..."))
373 text = self["text"].getText()
375 fp = file(self.configfile, 'w')
393 def keyDeleteForward(self):
394 self["text"].delete()
396 def keyDeleteBackward(self):
397 self["text"].deleteBackward()
399 def keyNumberGlobal(self, number):
400 print "pressed", number
401 self["text"].number(number)
404 class PacketManager(Screen):
406 <screen position="90,80" size="530,420" title="IPKG upgrade..." >
407 <widget source="list" render="Listbox" position="5,10" size="520,365" scrollbarMode="showOnDemand">
408 <convert type="TemplatedMultiContent">
410 MultiContentEntryText(pos = (5, 1), size = (440, 28), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name
411 MultiContentEntryText(pos = (5, 26), size = (440, 20), font=1, flags = RT_HALIGN_LEFT, text = 2), # index 2 is the description
412 MultiContentEntryPixmapAlphaTest(pos = (445, 2), size = (48, 48), png = 4), # index 4 is the status pixmap
413 MultiContentEntryPixmapAlphaTest(pos = (5, 50), size = (510, 2), png = 5), # index 4 is the div pixmap
415 "fonts": [gFont("Regular", 22),gFont("Regular", 14)],
420 <ePixmap pixmap="skin_default/buttons/red.png" position="10,380" zPosition="2" size="140,40" transparent="1" alphatest="on" />
421 <widget name="closetext" position="20,390" size="140,21" zPosition="10" font="Regular;21" transparent="1" />
422 <ePixmap pixmap="skin_default/buttons/green.png" position="160,380" zPosition="2" size="140,40" transparent="1" alphatest="on" />
423 <widget name="reloadtext" position="170,390" size="300,21" zPosition="10" font="Regular;21" transparent="1" />
426 def __init__(self, session, plugin_path, args = None):
427 Screen.__init__(self, session)
428 self.session = session
429 self.skin_path = plugin_path
431 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
436 "green": self.reload,
441 self["list"] = List(self.list)
442 self["closetext"] = Label(_("Close"))
443 self["reloadtext"] = Label(_("Reload"))
445 self.list_updating = True
447 self.installed_packetlist = {}
448 self.Console = Console()
451 self.cache_ttl = 86400 #600 is default, 0 disables, Seconds cache is considered valid (24h should be ok for caching ipkgs)
452 self.cache_file = '/usr/lib/enigma2/python/Plugins/SystemPlugins/SoftwareManager/packetmanager.cache' #Path to cache directory
453 self.oktext = _("\nAfter pressing OK, please wait!")
454 self.unwanted_extensions = ('-dbg', '-dev', '-doc', 'busybox')
456 self.ipkg = IpkgComponent()
457 self.ipkg.addCallback(self.ipkgCallback)
458 self.onShown.append(self.setWindowTitle)
459 self.onLayoutFinish.append(self.rebuildList)
463 if self.Console is not None:
464 if len(self.Console.appContainers):
465 for name in self.Console.appContainers.keys():
466 self.Console.kill(name)
470 if (os_path.exists(self.cache_file) == True):
471 remove(self.cache_file)
472 self.list_updating = True
475 def setWindowTitle(self):
476 self.setTitle(_("Packet manager"))
478 def setStatus(self,status = None):
481 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/div-h.png"))
482 if status == 'update':
483 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installable.png"))
484 self.statuslist.append(( _("Package list update"), '', _("Trying to download a new packetlist. Please wait..." ),'',statuspng, divpng ))
485 self['list'].setList(self.statuslist)
486 elif status == 'error':
487 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installed.png"))
488 self.statuslist.append(( _("Error"), '', _("There was an error downloading the packetlist. Please try again." ),'',statuspng, divpng ))
489 self['list'].setList(self.statuslist)
491 def rebuildList(self):
492 self.setStatus('update')
494 self.vc = valid_cache(self.cache_file, self.cache_ttl)
495 if self.cache_ttl > 0 and self.vc != 0:
497 self.buildPacketList()
500 if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0:
502 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
504 def go(self, returnValue = None):
505 cur = self["list"].getCurrent()
510 if status == 'installed':
511 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package }))
512 if len(self.cmdList):
513 self.session.openWithCallback(self.runRemove, MessageBox, _("Do you want to remove the package:\n") + package + "\n" + self.oktext)
514 elif status == 'upgradeable':
515 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package }))
516 if len(self.cmdList):
517 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to upgrade the package:\n") + package + "\n" + self.oktext)
518 elif status == "installable":
519 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package }))
520 if len(self.cmdList):
521 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to install the package:\n") + package + "\n" + self.oktext)
523 def runRemove(self, result):
525 self.session.openWithCallback(self.runRemoveFinished, Ipkg, cmdList = self.cmdList)
527 def runRemoveFinished(self):
528 self.session.openWithCallback(self.RemoveReboot, MessageBox, _("Remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
530 def RemoveReboot(self, result):
534 cur = self["list"].getCurrent()
536 item = self['list'].getIndex()
537 self.list[item] = self.buildEntryComponent(cur[0], cur[1], cur[2], 'installable')
538 self.cachelist[item] = [cur[0], cur[1], cur[2], 'installable']
539 self['list'].setList(self.list)
540 write_cache(self.cache_file, self.cachelist)
541 self.reloadPluginlist()
545 def runUpgrade(self, result):
547 self.session.openWithCallback(self.runUpgradeFinished, Ipkg, cmdList = self.cmdList)
549 def runUpgradeFinished(self):
550 self.session.openWithCallback(self.UpgradeReboot, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
552 def UpgradeReboot(self, result):
556 cur = self["list"].getCurrent()
558 item = self['list'].getIndex()
559 self.list[item] = self.buildEntryComponent(cur[0], cur[1], cur[2], 'installed')
560 self.cachelist[item] = [cur[0], cur[1], cur[2], 'installed']
561 self['list'].setList(self.list)
562 write_cache(self.cache_file, self.cachelist)
563 self.reloadPluginlist()
567 def ipkgCallback(self, event, param):
568 if event == IpkgComponent.EVENT_ERROR:
569 self.list_updating = False
570 self.setStatus('error')
571 elif event == IpkgComponent.EVENT_DONE:
572 if self.list_updating:
573 self.list_updating = False
575 self.Console = Console()
577 self.Console.ePopen(cmd, self.IpkgList_Finished)
578 #print event, "-", param
581 def IpkgList_Finished(self, result, retval, extra_args = None):
584 for x in result.splitlines():
585 split = x.split(' - ') #self.blacklisted_packages
586 if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions):
587 self.packetlist.append([split[0].strip(), split[1].strip(),split[2].strip()])
589 self.Console = Console()
590 cmd = "ipkg list_installed"
591 self.Console.ePopen(cmd, self.IpkgListInstalled_Finished)
593 def IpkgListInstalled_Finished(self, result, retval, extra_args = None):
595 self.installed_packetlist = {}
596 for x in result.splitlines():
597 split = x.split(' - ')
598 if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions):
599 self.installed_packetlist[split[0].strip()] = split[1].strip()
600 self.buildPacketList()
602 def buildEntryComponent(self, name, version, description, state):
603 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/div-h.png"))
604 if state == 'installed':
605 installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installed.png"))
606 return((name, version, description, state, installedpng, divpng))
607 elif state == 'upgradeable':
608 upgradeablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/upgradeable.png"))
609 return((name, version, description, state, upgradeablepng, divpng))
611 installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installable.png"))
612 return((name, version, description, state, installablepng, divpng))
614 def buildPacketList(self):
618 if self.cache_ttl > 0 and self.vc != 0:
619 print 'Loading packagelist cache from ',self.cache_file
621 self.cachelist = load_cache(self.cache_file)
622 if len(self.cachelist) > 0:
623 for x in self.cachelist:
624 self.list.append(self.buildEntryComponent(x[0], x[1], x[2], x[3]))
625 self['list'].setList(self.list)
629 if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0:
630 print 'rebuilding fresh package list'
631 for x in self.packetlist:
633 if self.installed_packetlist.has_key(x[0].strip()):
634 if self.installed_packetlist[x[0].strip()] == x[1].strip():
636 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status))
638 status = "upgradeable"
639 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status))
641 status = "installable"
642 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status))
643 if not any(x[0].strip().endswith(x) for x in self.unwanted_extensions):
644 self.cachelist.append([x[0].strip(), x[1].strip(), x[2].strip(), status])
645 write_cache(self.cache_file, self.cachelist)
646 self['list'].setList(self.list)
648 def reloadPluginlist(self):
649 plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
652 class PluginManager(Screen, DreamInfoHandler):
654 lastDownloadDate = None
657 <screen position="80,90" size="560,420" title="Plugin manager..." >
658 <widget source="list" render="Listbox" position="5,10" size="550,365" scrollbarMode="showOnDemand">
659 <convert type="TemplatedMultiContent">
662 MultiContentEntryText(pos = (30, 1), size = (500, 28), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name
663 MultiContentEntryText(pos = (30, 26), size = (500, 20), font=1, flags = RT_HALIGN_LEFT, text = 2), # index 2 is the description
664 MultiContentEntryPixmapAlphaTest(pos = (480, 2), size = (48, 48), png = 5), # index 5 is the status pixmap
665 MultiContentEntryPixmapAlphaTest(pos = (0, 50), size = (550, 2), png = 6), # index 6 is the div pixmap
666 MultiContentEntryPixmapAlphaTest(pos = (0, 10), size = (25, 25), png = 7), # index 7 is the selected pixmap
669 MultiContentEntryText(pos = (30, 0), size = (500, 24), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name
670 MultiContentEntryText(pos = (30, 26), size = (500, 14), font=1, flags = RT_HALIGN_LEFT, text = 1), # index 2 is the description
671 MultiContentEntryPixmapAlphaTest(pos = (0, 40), size = (550, 2), png = 3), # index 6 is the div pixmap
674 "fonts": [gFont("Regular", 22),gFont("Regular", 14)],
679 <ePixmap pixmap="skin_default/buttons/red.png" position="0,380" zPosition="2" size="140,40" transparent="1" alphatest="on" />
680 <widget name="closetext" position="0,380" zPosition="10" size="140,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
681 <ePixmap pixmap="skin_default/buttons/green.png" position="140,380" zPosition="2" size="140,40" transparent="1" alphatest="on" />
682 <widget name="installtext" position="140,380" zPosition="10" size="140,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
683 <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,380" zPosition="2" size="140,40" transparent="1" alphatest="on" />
684 <widget name="selecttext" position="280,380" zPosition="10" size="140,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
685 <ePixmap pixmap="skin_default/buttons/blue.png" position="420,380" zPosition="2" size="140,40" transparent="1" alphatest="on" />
686 <widget name="viewtext" position="420,380" zPosition="10" size="140,40" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
690 def __init__(self, session, plugin_path, args = None):
691 Screen.__init__(self, session)
692 self.session = session
693 self.skin_path = plugin_path
694 aboutInfo = about.getImageVersionString()
695 if aboutInfo.startswith("dev-"):
696 self.ImageVersion = 'Experimental'
698 self.ImageVersion = 'Stable'
699 self.language = language.getLanguage()[:2] # getLanguage returns e.g. "fi_FI" for "language_country"
701 DreamInfoHandler.__init__(self, self.statusCallback, blocking = False, neededTag = 'ALL_TAGS', neededFlag = self.ImageVersion, language = self.language)
702 self.directory = resolveFilename(SCOPE_METADIR)
704 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
709 "green": self.installPlugins,
710 "yellow": self.changeSelectionState,
716 self.selectedFiles = []
717 self.categoryList = []
718 self["list"] = List(self.list)
719 self["closetext"] = Label(_("Close"))
720 self["installtext"] = Label()
721 self["selecttext"] = Label()
722 self["viewtext"] = Label()
724 self.list_updating = True
726 self.installed_packetlist = {}
727 self.Console = Console()
729 self.oktext = _("\nAfter pressing OK, please wait!")
730 self.unwanted_extensions = ('-dbg', '-dev', '-doc')
732 self.ipkg = IpkgComponent()
733 self.ipkg.addCallback(self.ipkgCallback)
734 if not self.selectionChanged in self["list"].onSelectionChanged:
735 self["list"].onSelectionChanged.append(self.selectionChanged)
737 self["installtext"].hide()
738 self["selecttext"].hide()
739 self["viewtext"].hide()
741 self.currentSelectedTag = None
743 self.onShown.append(self.setWindowTitle)
744 self.onLayoutFinish.append(self.rebuildList)
746 def setWindowTitle(self):
747 self.setTitle(_("Plugin manager"))
750 if self.currList == "packages":
751 self.currList = "category"
752 self.currentSelectedTag = None
753 self["list"].style = "category"
754 self['list'].setList(self.categoryList)
757 if self.Console is not None:
758 if len(self.Console.appContainers):
759 for name in self.Console.appContainers.keys():
760 self.Console.kill(name)
764 if (os_path.exists(self.cache_file) == True):
765 remove(self.cache_file)
766 self.list_updating = True
769 def setState(self,status = None):
771 self.currList = "status"
773 self["installtext"].hide()
774 self["selecttext"].hide()
775 self["viewtext"].hide()
776 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/div-h.png"))
777 if status == 'update':
778 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installable.png"))
779 self.statuslist.append(( _("Package list update"), '', _("Trying to download a new packetlist. Please wait..." ),'', '', statuspng, divpng, None, '' ))
780 self["list"].style = "default"
781 self['list'].setList(self.statuslist)
782 elif status == 'sync':
783 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installable.png"))
784 self.statuslist.append(( _("Package list update"), '', _("Searching for new installed or removed packages. Please wait..." ),'', '', statuspng, divpng, None, '' ))
785 self["list"].style = "default"
786 self['list'].setList(self.statuslist)
787 elif status == 'error':
788 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installed.png"))
789 self.statuslist.append(( _("Error"), '', _("There was an error downloading the packetlist. Please try again." ),'', '', statuspng, divpng, None, '' ))
790 self["list"].style = "default"
791 self['list'].setList(self.statuslist)
793 def statusCallback(self, status, progress):
796 def selectionChanged(self):
797 current = self["list"].getCurrent()
799 if self.currList == "packages":
800 self["closetext"].setText(_("Back"))
801 self["closetext"].show()
802 self["installtext"].setText(_("Install/\nRemove"))
803 self["installtext"].show()
804 self["viewtext"].setText(_("Details"))
805 self["viewtext"].show()
806 if current[8] == False:
807 self["selecttext"].setText(_("Select"))
809 self["selecttext"].setText(_("Deselect"))
810 self["selecttext"].show()
811 elif self.currList == "category":
812 self["closetext"].setText(_("Close"))
813 self["closetext"].show()
814 self["installtext"].hide()
815 self["selecttext"].hide()
816 self["viewtext"].setText(_("View"))
817 self["viewtext"].show()
819 def changeSelectionState(self):
820 current = self["list"].getCurrent()
822 if current[8] is not '':
823 idx = self["list"].getIndex()
831 for entry in self.selectedFiles:
832 if entry[0] == detailsFile:
833 self.selectedFiles.remove(entry)
836 alreadyinList = False
837 for entry in self.selectedFiles:
838 if entry[0] == detailsFile:
840 if not alreadyinList:
841 self.selectedFiles.append((detailsFile,x[4],x[3]))
842 newList.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), x[3].strip(), x[4].strip(), selected = SelectState))
846 old_index = self["list"].index
848 self["list"].disable_callbacks = True
849 self["list"].list = self.list
850 self["list"].disable_callbacks = False
851 self["list"].setList(self.list)
852 self["list"].setIndex(old_index)
853 self["list"].updateList(self.list)
854 self.selectionChanged()
856 def rebuildList(self):
857 self.setState('update')
858 if not PluginManager.lastDownloadDate or (time() - PluginManager.lastDownloadDate) > 3600:
859 # Only update from internet once per hour
860 PluginManager.lastDownloadDate = time()
861 print "last update time > 1h"
862 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
864 print "last update time < 1h"
865 self.startInstallMetaPackage()
867 def ipkgCallback(self, event, param):
868 if event == IpkgComponent.EVENT_ERROR:
869 self.list_updating = False
870 self.setState('error')
871 elif event == IpkgComponent.EVENT_DONE:
872 self.startInstallMetaPackage()
875 def startInstallMetaPackage(self):
876 if self.list_updating:
877 self.list_updating = False
879 self.Console = Console()
880 cmd = "ipkg list" ### will change into "ipkg install enigma2-plugins-meta"
881 self.Console.ePopen(cmd, self.InstallMetaPackage_Finished)
883 def InstallMetaPackage_Finished(self, result, retval, extra_args = None):
885 self.fillPackagesIndexList()
887 self.Console = Console()
888 self.setState('sync')
889 cmd = "ipkg list_installed"
890 self.Console.ePopen(cmd, self.IpkgListInstalled_Finished)
892 def IpkgListInstalled_Finished(self, result, retval, extra_args = None):
894 self.installed_packetlist = {}
895 for x in result.splitlines():
896 split = x.split(' - ')
897 if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions):
898 self.installed_packetlist[split[0].strip()] = split[1].strip()
899 if self.currentSelectedTag is None:
900 self.buildCategoryList()
902 self.buildPacketList(self.currentSelectedTag)
904 def go(self, returnValue = None):
905 current = self["list"].getCurrent()
907 if self.currList == "category":
908 selectedTag = current[2]
909 self.buildPacketList(selectedTag)
910 elif self.currList == "packages":
911 #self.installPlugins()
912 #uncomment the above line and comment the bottom lines to have install functionality on OK
913 if current[8] is not '':
914 detailsfile = self.directory[0] + "/" + current[1]
915 if (os_path.exists(detailsfile) == True):
916 self.session.openWithCallback(self.detailsClosed, PluginDetails, self.skin_path, current)
918 self.session.open(MessageBox, _("Sorry, no Details available!"), MessageBox.TYPE_INFO)
919 def detailsClosed(self, result):
922 self.Console = Console()
923 self.setState('sync')
924 PluginManager.lastDownloadDate = time()
925 self.selectedFiles = []
927 self.Console.ePopen(cmd, self.InstallMetaPackage_Finished)
929 def buildEntryComponent(self, name, details, description, packagename, state, selected = False):
930 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/div-h.png"))
931 if selected is False:
932 selectedicon = LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/lock_off.png"))
934 selectedicon = LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/lock_on.png"))
936 if state == 'installed':
937 installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installed.png"))
938 return((name, details, description, packagename, state, installedpng, divpng, selectedicon, selected))
940 installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/installable.png"))
941 return((name, details, description, packagename, state, installablepng, divpng, selectedicon, selected))
943 def buildPacketList(self, categorytag = None):
944 if categorytag is not None:
945 self.currList = "packages"
946 self.currentSelectedTag = categorytag
947 #print self.packagesIndexlist
949 for package in self.packagesIndexlist[:]:
950 #print "package--->",package
951 prerequisites = package[0]["prerequisites"]
952 #print "prerequisite",prerequisites
953 if prerequisites.has_key("tag"):
954 for foundtag in prerequisites["tag"]:
955 if categorytag == foundtag:
956 attributes = package[0]["attributes"]
957 #print "attributes---->",attributes
958 self.packetlist.append([attributes["name"], attributes["details"], attributes["shortdescription"], attributes["packagename"]])
960 #print "self.packetlist---->",self.packetlist
961 for x in self.packetlist:
963 if self.installed_packetlist.has_key(x[3].strip()):
965 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), x[3].strip(), status, selected = False))
967 status = "installable"
968 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), x[3].strip(), status, selected = False))
970 self.list.sort(key=lambda x: x[0])
971 self["list"].style = "default"
972 self['list'].setList(self.list)
973 self["list"].updateList(self.list)
974 self.selectionChanged()
976 def buildCategoryList(self):
977 self.currList = "category"
978 #print self.packagesIndexlist
980 self.categoryList = []
981 for package in self.packagesIndexlist[:]:
982 #print "package--->",package
983 prerequisites = package[0]["prerequisites"]
984 #print "prerequisite",prerequisites
985 if prerequisites.has_key("tag"):
986 for foundtag in prerequisites["tag"]:
987 #print "found tag----",foundtag
988 if foundtag not in self.categories:
989 self.categories.append(foundtag)
990 self.categoryList.append(self.buildCategoryComponent(foundtag))
991 self.categoryList.sort(key=lambda x: x[0])
992 self["list"].style = "category"
993 self['list'].setList(self.categoryList)
994 self["list"].updateList(self.categoryList)
995 self.selectionChanged()
997 def buildCategoryComponent(self, tag = None):
998 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/div-h.png"))
1001 return(( _("System"), _("View list of available system extensions" ), tag, divpng ))
1003 return(( _("Skins"), _("View list of available skins" ), tag, divpng ))
1004 elif tag == 'Recording':
1005 return(( _("Recordings"), _("View list of available recording extensions" ), tag, divpng ))
1006 elif tag == 'Network':
1007 return(( _("Network"), _("View list of available networking extensions" ), tag, divpng ))
1009 return(( _("CommonInterface"), _("View list of available CommonInterface extensions" ), tag, divpng ))
1010 elif tag == 'Default':
1011 return(( _("Default Settings"), _("View list of available default settings" ), tag, divpng ))
1013 return(( _("Satteliteequipment"), _("View list of available Satteliteequipment extensions." ), tag, divpng ))
1014 elif tag == 'Software':
1015 return(( _("Software"), _("View list of available software extensions" ), tag, divpng ))
1016 elif tag == 'Multimedia':
1017 return(( _("Multimedia"), _("View list of available multimedia extensions." ), tag, divpng ))
1018 elif tag == 'Display':
1019 return(( _("Display and Userinterface"), _("View list of available Display and Userinterface extensions." ), tag, divpng ))
1021 return(( _("Electronic Program Guide"), _("View list of available EPG extensions." ), tag, divpng ))
1022 elif tag == 'Communication':
1023 return(( _("Communication"), _("View list of available communication extensions." ), tag, divpng ))
1024 else: # dynamically generate non existent tags
1025 return(( str(tag), _("View list of available ") + str(tag) + _(" extensions." ), tag, divpng ))
1027 def installPlugins(self):
1029 if self.selectedFiles and len(self.selectedFiles):
1030 for plugin in self.selectedFiles:
1031 #print "processing Plugin-->",plugin
1032 detailsfile = self.directory[0] + "/" + plugin[0]
1033 if (os_path.exists(detailsfile) == True):
1034 #print "plugin[1]-->",plugin[1]
1035 self.fillPackageDetails(plugin[0])
1036 self.package = self.packageDetails[0]
1037 if self.package[0].has_key("attributes"):
1038 self.attributes = self.package[0]["attributes"]
1039 if self.attributes.has_key("package"):
1040 self.packagefiles = self.attributes["package"]
1041 if plugin[1] == 'installed':
1042 if self.packagefiles:
1043 for package in self.packagefiles[:]:
1044 #print "removing package: ",package["name"]
1045 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package["name"] }))
1047 if self.packagefiles:
1048 for package in self.packagefiles[:]:
1049 #print "adding package: ",package["name"]
1050 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package["name"] }))
1052 if plugin[1] == 'installed':
1053 #print "removing package: ",plugin[2]
1054 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": plugin[2] }))
1056 #print "adding package: ",plugin[2]
1057 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": plugin[2] }))
1059 current = self["list"].getCurrent()
1061 if current[8] is not '':
1062 #print "current[4]-->",current[4]
1063 detailsfile = self.directory[0] + "/" + current[1]
1064 if (os_path.exists(detailsfile) == True):
1065 self.fillPackageDetails(current[1])
1066 self.package = self.packageDetails[0]
1067 if self.package[0].has_key("attributes"):
1068 self.attributes = self.package[0]["attributes"]
1069 if self.attributes.has_key("package"):
1070 self.packagefiles = self.attributes["package"]
1071 if current[4] == 'installed':
1072 if self.packagefiles:
1073 for package in self.packagefiles[:]:
1074 #print "removing package: ",package["name"]
1075 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package["name"] }))
1077 if self.packagefiles:
1078 for package in self.packagefiles[:]:
1079 #print "adding package: ",package["name"]
1080 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package["name"] }))
1082 if current[4] == 'installed':
1083 #print "removing package: ",current[0]
1084 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": current[3] }))
1086 #print "adding package: ",current[0]
1087 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": current[3] }))
1088 if len(self.cmdList):
1090 self.session.openWithCallback(self.runExecute, MessageBox, _("Do you want to continue installing or removing selected plugins?\n") + self.oktext)
1092 def runExecute(self, result):
1094 self.session.openWithCallback(self.runExecuteFinished, Ipkg, cmdList = self.cmdList)
1096 def runExecuteFinished(self):
1097 self.session.openWithCallback(self.ExecuteReboot, MessageBox, _("Install or remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
1099 def ExecuteReboot(self, result):
1103 self.reloadPluginlist()
1104 self.detailsClosed(True)
1108 def reloadPluginlist(self):
1109 plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
1112 class PluginDetails(Screen, DreamInfoHandler):
1114 <screen name="PluginDetails" position="60,90" size="600,420" title="PluginDetails..." >
1115 <widget name="author" position="10,10" size="500,25" zPosition="10" font="Regular;21" transparent="1" />
1116 <widget name="statuspic" position="550,0" size="48,48" alphatest="on"/>
1117 <widget name="divpic" position="0,40" size="600,2" alphatest="on"/>
1118 <widget name="detailtext" position="10,50" size="270,330" zPosition="10" font="Regular;21" transparent="1" halign="left" valign="top"/>
1119 <widget name="screenshot" position="290,50" size="300,330" alphatest="on"/>
1120 <ePixmap pixmap="skin_default/buttons/red.png" position="0,380" zPosition="2" size="140,40" transparent="1" alphatest="on" />
1121 <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" />
1122 <ePixmap pixmap="skin_default/buttons/green.png" position="140,380" zPosition="2" size="140,40" transparent="1" alphatest="on" />
1123 <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" />
1125 def __init__(self, session, plugin_path, packagedata = None):
1126 Screen.__init__(self, session)
1127 self.skin_path = plugin_path
1128 self.language = language.getLanguage()[:2] # getLanguage returns e.g. "fi_FI" for "language_country"
1129 self.attributes = None
1130 self.translatedAttributes = None
1131 DreamInfoHandler.__init__(self, self.statusCallback, blocking = False, language = self.language)
1132 self.directory = resolveFilename(SCOPE_METADIR)
1134 self.pluginname = packagedata[0]
1135 self.details = packagedata[1]
1136 self.pluginstate = packagedata[4]
1137 self.statuspicinstance = packagedata[5]
1138 self.divpicinstance = packagedata[6]
1139 self.fillPackageDetails(self.details)
1143 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
1149 "down": self.pageDown,
1150 "left": self.pageUp,
1151 "right": self.pageDown,
1154 self["statuspic"] = Pixmap()
1155 self["divpic"] = Pixmap()
1156 self["screenshot"] = Pixmap()
1157 self["closetext"] = Label(_("Close"))
1158 self["statetext"] = Label()
1159 self["detailtext"] = ScrollLabel()
1160 self["author"] = Label()
1161 self["statuspic"].hide()
1162 self["screenshot"].hide()
1163 self["divpic"].hide()
1165 self.package = self.packageDetails[0]
1166 if self.package[0].has_key("attributes"):
1167 self.attributes = self.package[0]["attributes"]
1168 if self.package[0].has_key("translation"):
1169 self.translatedAttributes = self.package[0]["translation"]
1172 self.oktext = _("\nAfter pressing OK, please wait!")
1173 self.picload = ePicLoad()
1174 self.picload.PictureData.get().append(self.paintScreenshotPixmapCB)
1175 self.onShown.append(self.setWindowTitle)
1176 self.onLayoutFinish.append(self.setInfos)
1178 def setWindowTitle(self):
1179 self.setTitle(_("Package details for: " + self.pluginname))
1185 self["detailtext"].pageUp()
1188 self["detailtext"].pageDown()
1190 def statusCallback(self, status, progress):
1194 if self.translatedAttributes.has_key("name"):
1195 self.pluginname = self.translatedAttributes["name"]
1196 elif self.attributes.has_key("name"):
1197 self.pluginname = self.attributes["name"]
1199 self.pluginname = _("unknown")
1201 if self.translatedAttributes.has_key("author"):
1202 self.author = self.translatedAttributes["author"]
1203 elif self.attributes.has_key("author"):
1204 self.author = self.attributes["author"]
1206 self.author = _("unknown")
1208 if self.translatedAttributes.has_key("description"):
1209 self.description = self.translatedAttributes["description"]
1210 elif self.attributes.has_key("description"):
1211 self.description = self.attributes["description"]
1213 self.description = _("No description available.")
1215 if self.translatedAttributes.has_key("screenshot"):
1216 self.loadThumbnail(self.translatedAttributes)
1218 self.loadThumbnail(self.attributes)
1220 self["author"].setText(_("Author: ") + self.author)
1221 self["detailtext"].setText(self.description.strip())
1222 if self.pluginstate == 'installable':
1223 self["statetext"].setText(_("Install"))
1225 self["statetext"].setText(_("Remove"))
1227 def loadThumbnail(self, entry):
1229 if entry.has_key("screenshot"):
1230 thumbnailUrl = entry["screenshot"]
1231 if thumbnailUrl is not None:
1232 self.thumbnail = "/tmp/" + thumbnailUrl.split('/')[-1]
1233 print "[PluginDetails] downloading screenshot " + thumbnailUrl + " to " + self.thumbnail
1234 client.downloadPage(thumbnailUrl,self.thumbnail).addCallback(self.setThumbnail).addErrback(self.fetchFailed)
1236 self.setThumbnail(noScreenshot = True)
1238 def setThumbnail(self, noScreenshot = False):
1239 if not noScreenshot:
1240 filename = self.thumbnail
1242 filename = resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/noprev.png")
1244 sc = AVSwitch().getFramebufferScale()
1245 self.picload.setPara((self["screenshot"].instance.size().width(), self["screenshot"].instance.size().height(), sc[0], sc[1], False, 1, "#00000000"))
1246 self.picload.startDecode(filename)
1248 if self.statuspicinstance != None:
1249 self["statuspic"].instance.setPixmap(self.statuspicinstance.__deref__())
1250 self["statuspic"].show()
1251 if self.divpicinstance != None:
1252 self["divpic"].instance.setPixmap(self.divpicinstance.__deref__())
1253 self["divpic"].show()
1255 def paintScreenshotPixmapCB(self, picInfo=None):
1256 ptr = self.picload.getData()
1258 self["screenshot"].instance.setPixmap(ptr.__deref__())
1259 self["screenshot"].show()
1261 self.setThumbnail(noScreenshot = True)
1264 if self.attributes.has_key("package"):
1265 self.packagefiles = self.attributes["package"]
1267 if self.pluginstate == 'installed':
1268 if self.packagefiles:
1269 for package in self.packagefiles[:]:
1270 #print "removing packagefile: ",package["name"]
1271 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package["name"] }))
1272 if len(self.cmdList):
1273 self.session.openWithCallback(self.runRemove, MessageBox, _("Do you want to remove the package:\n") + self.pluginname + "\n" + self.oktext)
1275 if self.packagefiles:
1276 for package in self.packagefiles[:]:
1277 #print "adding packagefile: ",package["name"]
1278 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package["name"] }))
1279 if len(self.cmdList):
1280 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to install the package:\n") + self.pluginname + "\n" + self.oktext)
1282 def runUpgrade(self, result):
1284 self.session.openWithCallback(self.runUpgradeFinished, Ipkg, cmdList = self.cmdList)
1286 def runUpgradeFinished(self):
1287 self.session.openWithCallback(self.UpgradeReboot, MessageBox, _("Installation finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
1289 def UpgradeReboot(self, result):
1297 def runRemove(self, result):
1299 self.session.openWithCallback(self.runRemoveFinished, Ipkg, cmdList = self.cmdList)
1301 def runRemoveFinished(self):
1302 self.session.openWithCallback(self.RemoveReboot, MessageBox, _("Remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
1304 def RemoveReboot(self, result):
1312 def reloadPluginlist(self):
1313 plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
1315 def fetchFailed(self,string):
1316 self.setThumbnail(noScreenshot = True)
1317 print "[PluginDetails] fetch failed " + string.getErrorMessage()
1320 class UpdatePlugin(Screen):
1322 <screen position="100,100" size="550,200" title="Software Update..." >
1323 <widget name="activityslider" position="0,0" size="550,5" />
1324 <widget name="slider" position="0,100" size="550,30" />
1325 <widget name="package" position="10,30" size="540,20" font="Regular;18"/>
1326 <widget name="status" position="10,60" size="540,45" font="Regular;18"/>
1329 def __init__(self, session, args = None):
1330 self.skin = UpdatePlugin.skin
1331 Screen.__init__(self, session)
1333 self.sliderPackages = { "dreambox-dvb-modules": 1, "enigma2": 2, "tuxbox-image-info": 3 }
1335 self.slider = Slider(0, 4)
1336 self["slider"] = self.slider
1337 self.activityslider = Slider(0, 100)
1338 self["activityslider"] = self.activityslider
1339 self.status = Label(_("Upgrading Dreambox... Please wait"))
1340 self["status"] = self.status
1341 self.package = Label()
1342 self["package"] = self.package
1348 self.activityTimer = eTimer()
1349 self.activityTimer.callback.append(self.doActivityTimer)
1350 self.activityTimer.start(100, False)
1352 self.ipkg = IpkgComponent()
1353 self.ipkg.addCallback(self.ipkgCallback)
1355 self.updating = True
1356 self.package.setText(_("Package list update"))
1357 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
1359 self["actions"] = ActionMap(["WizardActions"],
1365 def doActivityTimer(self):
1367 if self.activity == 100:
1369 self.activityslider.setValue(self.activity)
1371 def ipkgCallback(self, event, param):
1372 if event == IpkgComponent.EVENT_DOWNLOAD:
1373 self.status.setText(_("Downloading"))
1374 elif event == IpkgComponent.EVENT_UPGRADE:
1375 if self.sliderPackages.has_key(param):
1376 self.slider.setValue(self.sliderPackages[param])
1377 self.package.setText(param)
1378 self.status.setText(_("Upgrading"))
1380 elif event == IpkgComponent.EVENT_INSTALL:
1381 self.package.setText(param)
1382 self.status.setText(_("Installing"))
1384 elif event == IpkgComponent.EVENT_CONFIGURING:
1385 self.package.setText(param)
1386 self.status.setText(_("Configuring"))
1387 elif event == IpkgComponent.EVENT_MODIFIED:
1388 self.session.openWithCallback(
1389 self.modificationCallback,
1391 _("A configuration file (%s) was modified since Installation.\nDo you want to keep your version?") % (param)
1393 elif event == IpkgComponent.EVENT_ERROR:
1395 elif event == IpkgComponent.EVENT_DONE:
1397 self.updating = False
1398 self.ipkg.startCmd(IpkgComponent.CMD_UPGRADE, args = {'test_only': False})
1399 elif self.error == 0:
1400 self.slider.setValue(4)
1402 self.activityTimer.stop()
1403 self.activityslider.setValue(0)
1405 self.package.setText("")
1406 self.status.setText(_("Done - Installed or upgraded %d packages") % self.packages)
1408 self.activityTimer.stop()
1409 self.activityslider.setValue(0)
1410 error = _("your dreambox might be unusable now. Please consult the manual for further assistance before rebooting your dreambox.")
1411 if self.packages == 0:
1412 error = _("No packages were upgraded yet. So you can check your network and try again.")
1414 error = _("Your dreambox isn't connected to the internet properly. Please check it and try again.")
1415 self.status.setText(_("Error") + " - " + error)
1416 #print event, "-", param
1419 def modificationCallback(self, res):
1420 self.ipkg.write(res and "N" or "Y")
1423 if not self.ipkg.isRunning():
1424 if self.packages != 0 and self.error == 0:
1425 self.session.openWithCallback(self.exitAnswer, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"))
1429 def exitAnswer(self, result):
1430 if result is not None and result:
1435 class IpkgInstaller(Screen):
1437 <screen position="100,100" size="550,400" title="..." >
1438 <widget name="red" halign="center" valign="center" position="0,0" size="140,60" backgroundColor="red" font="Regular;21" />
1439 <widget name="green" halign="center" valign="center" position="140,0" text="Install selected" size="140,60" backgroundColor="green" font="Regular;21" />
1440 <widget name="yellow" halign="center" valign="center" position="280,0" size="140,60" backgroundColor="yellow" font="Regular;21" />
1441 <widget name="blue" halign="center" valign="center" position="420,0" size="140,60" backgroundColor="blue" font="Regular;21" />
1442 <widget name="list" position="0,60" size="550,360" />
1446 def __init__(self, session, list):
1447 self.skin = IpkgInstaller.skin
1448 Screen.__init__(self, session)
1450 self.list = SelectionList()
1451 self["list"] = self.list
1452 for listindex in range(len(list)):
1453 self.list.addSelection(list[listindex], list[listindex], listindex, True)
1455 self["red"] = Label()
1456 self["green"] = Label()
1457 self["yellow"] = Label()
1458 self["blue"] = Label()
1460 self["actions"] = ActionMap(["OkCancelActions", "ColorActions"],
1462 "ok": self.list.toggleSelection,
1463 "cancel": self.close,
1464 "green": self.install
1468 list = self.list.getSelectionsList()
1471 cmdList.append((IpkgComponent.CMD_INSTALL, { "package": item[1] }))
1472 self.session.open(Ipkg, cmdList = cmdList)
1474 def filescan_open(list, session, **kwargs):
1475 filelist = [x.path for x in list]
1476 session.open(IpkgInstaller, filelist) # list
1478 def filescan(**kwargs):
1479 from Components.Scanner import Scanner, ScanPath
1481 Scanner(mimetypes = ["application/x-debian-package"],
1484 ScanPath(path = "ipk", with_subdirs = True),
1485 ScanPath(path = "", with_subdirs = False),
1488 description = _("Install software updates..."),
1489 openfnc = filescan_open, )
1493 def UpgradeMain(session, **kwargs):
1494 session.open(UpdatePluginMenu)
1496 def startSetup(menuid):
1497 if menuid != "setup":
1499 return [(_("Software manager"), UpgradeMain, "software_manager", 50)]
1501 def Plugins(path, **kwargs):
1505 PluginDescriptor(name=_("Software manager"), description=_("Manage your receiver's software"), where = PluginDescriptor.WHERE_MENU, fnc=startSetup),
1506 PluginDescriptor(name=_("Ipkg"), where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)
1508 if config.usage.setup_level.index >= 2: # expert+
1509 list.append(PluginDescriptor(name=_("Software manager"), description=_("Manage your receiver's software"), where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc=UpgradeMain))