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 Components.Network import iNetwork
27 from Tools.Directories import pathExists, fileExists, resolveFilename, SCOPE_PLUGINS, SCOPE_CURRENT_PLUGIN, SCOPE_CURRENT_SKIN, SCOPE_METADIR
28 from Tools.LoadPixmap import LoadPixmap
29 from enigma import eTimer, quitMainloop, RT_HALIGN_LEFT, RT_VALIGN_CENTER, eListboxPythonMultiContent, eListbox, gFont, getDesktop, ePicLoad
30 from cPickle import dump, load
31 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
32 from time import time, gmtime, strftime, localtime
33 from stat import ST_MTIME
34 from datetime import date
35 from twisted.web import client
36 from twisted.internet import reactor
38 from ImageWizard import ImageWizard
39 from BackupRestore import BackupSelection, RestoreMenu, BackupScreen, RestoreScreen, getBackupPath, getBackupFilename
40 from SoftwareTools import iSoftwareTools
42 config.plugins.configurationbackup = ConfigSubsection()
43 config.plugins.configurationbackup.backuplocation = ConfigText(default = '/media/hdd/', visible_width = 50, fixed_size = False)
44 config.plugins.configurationbackup.backupdirs = ConfigLocations(default=['/etc/enigma2/', '/etc/network/interfaces', '/etc/wpa_supplicant.conf', '/etc/resolv.conf', '/etc/default_gw', '/etc/hostname'])
46 def write_cache(cache_file, cache_data):
48 if not os_path.isdir( os_path.dirname(cache_file) ):
50 mkdir( os_path.dirname(cache_file) )
52 print os_path.dirname(cache_file), 'is a file'
53 fd = open(cache_file, 'w')
54 dump(cache_data, fd, -1)
57 def valid_cache(cache_file, cache_ttl):
58 #See if the cache file exists and is still living
60 mtime = stat(cache_file)[ST_MTIME]
64 if (curr_time - mtime) > cache_ttl:
69 def load_cache(cache_file):
77 class UpdatePluginMenu(Screen):
79 <screen name="UpdatePluginMenu" position="center,center" size="610,410" title="Software management" >
80 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
81 <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" />
82 <ePixmap pixmap="skin_default/border_menu_350.png" position="5,50" zPosition="1" size="350,300" transparent="1" alphatest="on" />
83 <widget source="menu" render="Listbox" position="15,60" size="330,290" scrollbarMode="showOnDemand">
84 <convert type="TemplatedMultiContent">
86 MultiContentEntryText(pos = (2, 2), size = (330, 24), flags = RT_HALIGN_LEFT, text = 1), # index 0 is the MenuText,
88 "fonts": [gFont("Regular", 22)],
93 <widget source="menu" render="Listbox" position="360,50" size="240,300" scrollbarMode="showNever" selectionDisabled="1">
94 <convert type="TemplatedMultiContent">
96 MultiContentEntryText(pos = (2, 2), size = (240, 300), flags = RT_HALIGN_CENTER|RT_VALIGN_CENTER|RT_WRAP, text = 2), # index 2 is the Description,
98 "fonts": [gFont("Regular", 22)],
103 <widget source="status" render="Label" position="5,360" zPosition="10" size="600,50" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
106 def __init__(self, session, args = 0):
107 Screen.__init__(self, session)
108 self.skin_path = plugin_path
111 self.oktext = _("\nPress OK on your remote control to continue.")
113 self.backupdirs = ' '.join( config.plugins.configurationbackup.backupdirs.value )
115 self.list.append(("install-extensions", _("Manage extensions"), _("\nManage extensions or plugins for your Dreambox" ) + self.oktext, None))
116 self.list.append(("software-update", _("Software update"), _("\nOnline update of your Dreambox software." ) + self.oktext, None))
117 self.list.append(("software-restore", _("Software restore"), _("\nRestore your Dreambox with a new firmware." ) + self.oktext, None))
118 self.list.append(("system-backup", _("Backup system settings"), _("\nBackup your Dreambox settings." ) + self.oktext, None))
119 self.list.append(("system-restore",_("Restore system settings"), _("\nRestore your Dreambox settings." ) + self.oktext, None))
120 self.list.append(("ipkg-install", _("Install local extension"), _("\nScan for local extensions and install them." ) + self.oktext, None))
121 for p in plugins.getPlugins(PluginDescriptor.WHERE_SOFTWAREMANAGER):
122 if p.__call__.has_key("SoftwareSupported"):
123 callFnc = p.__call__["SoftwareSupported"](None)
124 if callFnc is not None:
125 if p.__call__.has_key("menuEntryName"):
126 menuEntryName = p.__call__["menuEntryName"](None)
128 menuEntryName = _('Extended Software')
129 if p.__call__.has_key("menuEntryDescription"):
130 menuEntryDescription = p.__call__["menuEntryDescription"](None)
132 menuEntryDescription = _('Extended Software Plugin')
133 self.list.append(('default-plugin', menuEntryName, menuEntryDescription + self.oktext, callFnc))
134 if config.usage.setup_level.index >= 2: # expert+
135 self.list.append(("advanced", _("Advanced Options"), _("\nAdvanced options and settings." ) + self.oktext, None))
137 self.list.append(("advancedrestore", _("Advanced restore"), _("\nRestore your backups by date." ) + self.oktext, None))
138 self.list.append(("backuplocation", _("Choose backup location"), _("\nSelect your backup device.\nCurrent device: " ) + config.plugins.configurationbackup.backuplocation.value + self.oktext, None))
139 self.list.append(("backupfiles", _("Choose backup files"), _("Select files for backup. Currently selected:\n" ) + self.backupdirs + self.oktext, None))
140 if config.usage.setup_level.index >= 2: # expert+
141 self.list.append(("ipkg-manager", _("Packet management"), _("\nView, install and remove available or installed packages." ) + self.oktext, None))
142 self.list.append(("ipkg-source",_("Choose upgrade source"), _("\nEdit the upgrade source address." ) + self.oktext, None))
143 for p in plugins.getPlugins(PluginDescriptor.WHERE_SOFTWAREMANAGER):
144 if p.__call__.has_key("AdvancedSoftwareSupported"):
145 callFnc = p.__call__["AdvancedSoftwareSupported"](None)
146 if callFnc is not None:
147 if p.__call__.has_key("menuEntryName"):
148 menuEntryName = p.__call__["menuEntryName"](None)
150 menuEntryName = _('Advanced Software')
151 if p.__call__.has_key("menuEntryDescription"):
152 menuEntryDescription = p.__call__["menuEntryDescription"](None)
154 menuEntryDescription = _('Advanced Software Plugin')
155 self.list.append(('advanced-plugin', menuEntryName, menuEntryDescription + self.oktext, callFnc))
157 self["menu"] = List(self.list)
158 self["key_red"] = StaticText(_("Close"))
159 self["status"] = StaticText("")
161 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions", "InfobarEPGActions"],
167 self.onLayoutFinish.append(self.layoutFinished)
168 self.backuppath = getBackupPath()
169 self.backupfile = getBackupFilename()
170 self.fullbackupfilename = self.backuppath + "/" + self.backupfile
171 self.onShown.append(self.setWindowTitle)
172 #self.onClose.append(self.cleanup)
174 def layoutFinished(self):
176 self["menu"].index = idx
177 #self.getUpdateInfos()
179 def setWindowTitle(self):
180 self.setTitle(_("Software management"))
183 iNetwork.stopPingConsole()
184 iSoftwareTools.cleanupSoftwareTools()
186 def getUpdateInfos(self):
188 if iSoftwareTools.NetworkConnectionAvailable == True:
189 if iSoftwareTools.list_updating is False:
190 if iSoftwareTools.available_updates is not 0:
191 self.text = _("There are at least ") + str(iSoftwareTools.available_updates) + _(" updates available.")
193 self.text = "" #_("There are no updates available.")
195 if iSoftwareTools.available_updates is not 0:
196 self.text = _("There are at least ") + str(iSoftwareTools.available_updates) + _(" updates available.")
198 self.text = "" #_("There are no updates available.")
199 self.text += "\n" + _("A search for available updates is currently in progress.")
201 self.text = _("No network connection available.")
202 self["status"].setText(self.text)
206 #iNetwork.stopPingConsole()
207 current = self["menu"].getCurrent()
209 currentEntry = current[0]
211 if (currentEntry == "software-update"):
212 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to update your Dreambox?")+"\n"+_("\nAfter pressing OK, please wait!"))
213 elif (currentEntry == "software-restore"):
214 self.session.open(ImageWizard)
215 elif (currentEntry == "install-extensions"):
216 self.session.open(PluginManager, self.skin_path)
217 elif (currentEntry == "system-backup"):
218 self.session.openWithCallback(self.backupDone,BackupScreen, runBackup = True)
219 elif (currentEntry == "system-restore"):
220 if os_path.exists(self.fullbackupfilename):
221 self.session.openWithCallback(self.startRestore, MessageBox, _("Are you sure you want to restore your Enigma2 backup?\nEnigma2 will restart after the restore"))
223 self.session.open(MessageBox, _("Sorry no backups found!"), MessageBox.TYPE_INFO, timeout = 10)
224 elif (currentEntry == "ipkg-install"):
226 from Plugins.Extensions.MediaScanner.plugin import main
229 self.session.open(MessageBox, _("Sorry MediaScanner is not installed!"), MessageBox.TYPE_INFO, timeout = 10)
230 elif (currentEntry == "default-plugin"):
231 self.extended = current[3]
232 self.extended(self.session, None)
233 elif (currentEntry == "advanced"):
234 self.session.open(UpdatePluginMenu, 1)
236 if (currentEntry == "ipkg-manager"):
237 self.session.open(PacketManager, self.skin_path)
238 elif (currentEntry == "backuplocation"):
239 parts = [ (r.description, r.mountpoint, self.session) for r in harddiskmanager.getMountedPartitions(onlyhotplug = False)]
241 if not access(x[1], F_OK|R_OK|W_OK) or x[1] == '/':
244 if x[1].startswith('/autofs/'):
247 self.session.openWithCallback(self.backuplocation_choosen, ChoiceBox, title = _("Please select medium to use as backup location"), list = parts)
248 elif (currentEntry == "backupfiles"):
249 self.session.openWithCallback(self.backupfiles_choosen,BackupSelection)
250 elif (currentEntry == "advancedrestore"):
251 self.session.open(RestoreMenu, self.skin_path)
252 elif (currentEntry == "ipkg-source"):
253 self.session.open(IPKGMenu, self.skin_path)
254 elif (currentEntry == "advanced-plugin"):
255 self.extended = current[3]
256 self.extended(self.session, None)
258 def backupfiles_choosen(self, ret):
259 self.backupdirs = ' '.join( config.plugins.configurationbackup.backupdirs.value )
261 def backuplocation_choosen(self, option):
262 if option is not None:
263 config.plugins.configurationbackup.backuplocation.value = str(option[1])
264 config.plugins.configurationbackup.backuplocation.save()
265 config.plugins.configurationbackup.save()
267 self.createBackupfolders()
269 def runUpgrade(self, result):
271 self.session.open(UpdatePlugin, self.skin_path)
273 def createBackupfolders(self):
274 print "Creating backup folder if not already there..."
275 self.backuppath = getBackupPath()
277 if (os_path.exists(self.backuppath) == False):
278 makedirs(self.backuppath)
280 self.session.open(MessageBox, _("Sorry, your backup destination is not writeable.\n\nPlease choose another one."), MessageBox.TYPE_INFO, timeout = 10)
282 def backupDone(self,retval = None):
284 self.session.open(MessageBox, _("Backup done."), MessageBox.TYPE_INFO, timeout = 10)
286 self.session.open(MessageBox, _("Backup failed."), MessageBox.TYPE_INFO, timeout = 10)
288 def startRestore(self, ret = False):
291 self.session.open(RestoreScreen, runRestore = True)
294 class PluginManager(Screen, DreamInfoHandler):
297 <screen name="PluginManager" position="center,center" size="560,440" title="Extensions management" >
298 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
299 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
300 <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
301 <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" alphatest="on" />
302 <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" />
303 <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" />
304 <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" />
305 <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" />
306 <widget source="list" render="Listbox" position="5,50" size="550,360" scrollbarMode="showOnDemand">
307 <convert type="TemplatedMultiContent">
310 MultiContentEntryText(pos = (30, 1), size = (470, 24), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name
311 MultiContentEntryText(pos = (30, 25), size = (470, 24), font=1, flags = RT_HALIGN_LEFT, text = 2), # index 2 is the description
312 MultiContentEntryPixmapAlphaTest(pos = (475, 0), size = (48, 48), png = 5), # index 5 is the status pixmap
313 MultiContentEntryPixmapAlphaTest(pos = (0, 49), size = (550, 2), png = 6), # index 6 is the div pixmap
316 MultiContentEntryText(pos = (30, 0), size = (500, 22), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name
317 MultiContentEntryText(pos = (30, 22), size = (500, 16), font=2, flags = RT_HALIGN_LEFT, text = 1), # index 1 is the description
318 MultiContentEntryPixmapAlphaTest(pos = (0, 38), size = (550, 2), png = 3), # index 3 is the div pixmap
321 "fonts": [gFont("Regular", 22),gFont("Regular", 20),gFont("Regular", 16)],
326 <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" />
329 def __init__(self, session, plugin_path = None, args = None):
330 Screen.__init__(self, session)
331 self.session = session
332 self.skin_path = plugin_path
333 if self.skin_path == None:
334 self.skin_path = resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager")
336 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions", "InfobarEPGActions", "HelpActions" ],
338 "ok": self.handleCurrent,
341 "green": self.handleCurrent,
342 "yellow": self.handleSelected,
343 "showEventInfo": self.handleSelected,
344 "displayHelp": self.handleHelp,
349 self.selectedFiles = []
350 self.categoryList = []
352 self["list"] = List(self.list)
353 self["key_red"] = StaticText(_("Close"))
354 self["key_green"] = StaticText("")
355 self["key_yellow"] = StaticText("")
356 self["key_blue"] = StaticText("")
357 self["status"] = StaticText("")
360 self.oktext = _("\nAfter pressing OK, please wait!")
361 if not self.selectionChanged in self["list"].onSelectionChanged:
362 self["list"].onSelectionChanged.append(self.selectionChanged)
365 self.currentSelectedTag = None
366 self.currentSelectedIndex = None
367 self.currentSelectedPackage = None
368 self.saved_currentSelectedPackage = None
370 self.onShown.append(self.setWindowTitle)
371 self.onLayoutFinish.append(self.getUpdateInfos)
373 def setWindowTitle(self):
374 self.setTitle(_("Extensions management"))
377 if self.currList == "packages":
378 self.currList = "category"
379 self.currentSelectedTag = None
380 self["list"].style = "category"
381 self['list'].setList(self.categoryList)
382 self["list"].setIndex(self.currentSelectedIndex)
383 self["list"].updateList(self.categoryList)
384 self.selectionChanged()
386 iSoftwareTools.cleanupSoftwareTools()
387 self.prepareInstall()
388 if len(self.cmdList):
389 self.session.openWithCallback(self.runExecute, PluginManagerInfo, self.skin_path, self.cmdList)
393 def handleHelp(self):
394 if self.currList != "status":
395 self.session.open(PluginManagerHelp, self.skin_path)
397 def setState(self,status = None):
399 self.currList = "status"
401 self["key_green"].setText("")
402 self["key_blue"].setText("")
403 self["key_yellow"].setText("")
404 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png"))
405 if status == 'update':
406 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgrade.png"))
407 self.statuslist.append(( _("Updating software catalog"), '', _("Searching for available updates. Please wait..." ),'', '', statuspng, divpng, None, '' ))
408 self["list"].style = "default"
409 self['list'].setList(self.statuslist)
410 elif status == 'sync':
411 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgrade.png"))
412 self.statuslist.append(( _("Package list update"), '', _("Searching for new installed or removed packages. Please wait..." ),'', '', statuspng, divpng, None, '' ))
413 self["list"].style = "default"
414 self['list'].setList(self.statuslist)
415 elif status == 'error':
416 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png"))
417 self.statuslist.append(( _("Error"), '', _("There was an error downloading the packetlist. Please try again." ),'', '', statuspng, divpng, None, '' ))
418 self["list"].style = "default"
419 self['list'].setList(self.statuslist)
421 def getUpdateInfos(self):
422 self.setState('update')
423 iSoftwareTools.startSoftwareTools(self.getUpdateInfosCB)
425 def getUpdateInfosCB(self, retval = None):
426 if retval is not None:
428 if iSoftwareTools.available_updates is not 0:
429 self["status"].setText(_("There are at least ") + str(iSoftwareTools.available_updates) + _(" updates available."))
431 self["status"].setText(_("There are no updates available."))
433 elif retval is False:
434 self.setState('error')
435 self["status"].setText(_("No network connection available."))
437 def rebuildList(self, retval = None):
438 if self.currentSelectedTag is None:
439 self.buildCategoryList()
441 self.buildPacketList(self.currentSelectedTag)
443 def selectionChanged(self):
444 current = self["list"].getCurrent()
445 self["status"].setText("")
447 if self.currList == "packages":
448 self["key_red"].setText(_("Back"))
449 if current[4] == 'installed':
450 self["key_green"].setText(_("Uninstall"))
451 elif current[4] == 'installable':
452 self["key_green"].setText(_("Install"))
453 elif current[4] == 'remove':
454 self["key_green"].setText(_("Undo uninstall"))
455 elif current[4] == 'install':
456 self["key_green"].setText(_("Undo install"))
457 self["key_yellow"].setText(_("View details"))
458 self["key_blue"].setText("")
459 if len(self.selectedFiles) == 0 and iSoftwareTools.available_updates is not 0:
460 self["status"].setText(_("There are at least ") + str(iSoftwareTools.available_updates) + _(" updates available."))
461 elif len(self.selectedFiles) is not 0:
462 self["status"].setText(str(len(self.selectedFiles)) + _(" packages selected."))
464 self["status"].setText(_("There are currently no outstanding actions."))
465 elif self.currList == "category":
466 self["key_red"].setText(_("Close"))
467 self["key_green"].setText("")
468 self["key_yellow"].setText("")
469 self["key_blue"].setText("")
470 if len(self.selectedFiles) == 0 and iSoftwareTools.available_updates is not 0:
471 self["status"].setText(_("There are at least ") + str(iSoftwareTools.available_updates) + _(" updates available."))
472 self["key_yellow"].setText(_("Update"))
473 elif len(self.selectedFiles) is not 0:
474 self["status"].setText(str(len(self.selectedFiles)) + _(" packages selected."))
475 self["key_yellow"].setText(_("Process"))
477 self["status"].setText(_("There are currently no outstanding actions."))
479 def getSelectionState(self, detailsFile):
480 for entry in self.selectedFiles:
481 if entry[0] == detailsFile:
485 def handleCurrent(self):
486 current = self["list"].getCurrent()
488 if self.currList == "category":
489 self.currentSelectedIndex = self["list"].index
490 selectedTag = current[2]
491 self.buildPacketList(selectedTag)
492 elif self.currList == "packages":
493 if current[7] is not '':
494 idx = self["list"].getIndex()
495 detailsFile = self.list[idx][1]
496 if self.list[idx][7] == True:
497 for entry in self.selectedFiles:
498 if entry[0] == detailsFile:
499 self.selectedFiles.remove(entry)
501 alreadyinList = False
502 for entry in self.selectedFiles:
503 if entry[0] == detailsFile:
505 if not alreadyinList:
506 self.selectedFiles.append((detailsFile,current[4],current[3]))
507 self.currentSelectedPackage = ((detailsFile,current[4],current[3]))
508 if current[4] == 'installed':
509 self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'remove', True)
510 elif current[4] == 'installable':
511 self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'install', True)
512 elif current[4] == 'remove':
513 self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'installed', False)
514 elif current[4] == 'install':
515 self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'installable',False)
516 self["list"].setList(self.list)
517 self["list"].setIndex(idx)
518 self["list"].updateList(self.list)
519 self.selectionChanged()
521 def handleSelected(self):
522 current = self["list"].getCurrent()
524 if self.currList == "packages":
525 if current[7] is not '':
526 detailsfile = iSoftwareTools.directory[0] + "/" + current[1]
527 if (os_path.exists(detailsfile) == True):
528 self.saved_currentSelectedPackage = self.currentSelectedPackage
529 self.session.openWithCallback(self.detailsClosed, PluginDetails, self.skin_path, current)
531 self.session.open(MessageBox, _("Sorry, no Details available!"), MessageBox.TYPE_INFO, timeout = 10)
532 elif self.currList == "category":
533 self.prepareInstall()
534 if len(self.cmdList):
535 self.session.openWithCallback(self.runExecute, PluginManagerInfo, self.skin_path, self.cmdList)
537 def detailsClosed(self, result = None):
538 if result is not None:
539 if result is not False:
540 self.setState('sync')
541 iSoftwareTools.lastDownloadDate = time()
542 for entry in self.selectedFiles:
543 if entry == self.saved_currentSelectedPackage:
544 self.selectedFiles.remove(entry)
545 iSoftwareTools.startIpkgListInstalled(self.rebuildList)
547 def buildEntryComponent(self, name, details, description, packagename, state, selected = False):
548 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png"))
549 installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installed.png"))
550 installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installable.png"))
551 removepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png"))
552 installpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/install.png"))
553 if state == 'installed':
554 return((name, details, description, packagename, state, installedpng, divpng, selected))
555 elif state == 'installable':
556 return((name, details, description, packagename, state, installablepng, divpng, selected))
557 elif state == 'remove':
558 return((name, details, description, packagename, state, removepng, divpng, selected))
559 elif state == 'install':
560 return((name, details, description, packagename, state, installpng, divpng, selected))
562 def buildPacketList(self, categorytag = None):
563 if categorytag is not None:
564 self.currList = "packages"
565 self.currentSelectedTag = categorytag
567 for package in iSoftwareTools.packagesIndexlist[:]:
568 prerequisites = package[0]["prerequisites"]
569 if prerequisites.has_key("tag"):
570 for foundtag in prerequisites["tag"]:
571 if categorytag == foundtag:
572 attributes = package[0]["attributes"]
573 if attributes.has_key("packagetype"):
574 if attributes["packagetype"] == "internal":
576 self.packetlist.append([attributes["name"], attributes["details"], attributes["shortdescription"], attributes["packagename"]])
578 self.packetlist.append([attributes["name"], attributes["details"], attributes["shortdescription"], attributes["packagename"]])
580 for x in self.packetlist:
583 details = x[1].strip()
584 description = x[2].strip()
585 packagename = x[3].strip()
586 selectState = self.getSelectionState(details)
587 if iSoftwareTools.installed_packetlist.has_key(packagename):
588 if selectState == True:
592 self.list.append(self.buildEntryComponent(name, details, description, packagename, status, selected = selectState))
594 if selectState == True:
597 status = "installable"
598 self.list.append(self.buildEntryComponent(name, details, description, packagename, status, selected = selectState))
600 self.list.sort(key=lambda x: x[0])
601 self["list"].style = "default"
602 self['list'].setList(self.list)
603 self["list"].updateList(self.list)
604 self.selectionChanged()
606 def buildCategoryList(self):
607 self.currList = "category"
609 self.categoryList = []
610 for package in iSoftwareTools.packagesIndexlist[:]:
611 prerequisites = package[0]["prerequisites"]
612 if prerequisites.has_key("tag"):
613 for foundtag in prerequisites["tag"]:
614 attributes = package[0]["attributes"]
615 if foundtag not in self.categories:
616 self.categories.append(foundtag)
617 self.categoryList.append(self.buildCategoryComponent(foundtag))
618 self.categoryList.sort(key=lambda x: x[0])
619 self["list"].style = "category"
620 self['list'].setList(self.categoryList)
621 self["list"].updateList(self.categoryList)
622 self.selectionChanged()
624 def buildCategoryComponent(self, tag = None):
625 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png"))
628 return(( _("System"), _("View list of available system extensions" ), tag, divpng ))
630 return(( _("Skins"), _("View list of available skins" ), tag, divpng ))
631 elif tag == 'Recording':
632 return(( _("Recordings"), _("View list of available recording extensions" ), tag, divpng ))
633 elif tag == 'Network':
634 return(( _("Network"), _("View list of available networking extensions" ), tag, divpng ))
636 return(( _("CommonInterface"), _("View list of available CommonInterface extensions" ), tag, divpng ))
637 elif tag == 'Default':
638 return(( _("Default Settings"), _("View list of available default settings" ), tag, divpng ))
640 return(( _("Satellite equipment"), _("View list of available Satellite equipment extensions." ), tag, divpng ))
641 elif tag == 'Software':
642 return(( _("Software"), _("View list of available software extensions" ), tag, divpng ))
643 elif tag == 'Multimedia':
644 return(( _("Multimedia"), _("View list of available multimedia extensions." ), tag, divpng ))
645 elif tag == 'Display':
646 return(( _("Display and Userinterface"), _("View list of available Display and Userinterface extensions." ), tag, divpng ))
648 return(( _("Electronic Program Guide"), _("View list of available EPG extensions." ), tag, divpng ))
649 elif tag == 'Communication':
650 return(( _("Communication"), _("View list of available communication extensions." ), tag, divpng ))
651 else: # dynamically generate non existent tags
652 return(( str(tag), _("View list of available ") + str(tag) + _(" extensions." ), tag, divpng ))
654 def prepareInstall(self):
656 if iSoftwareTools.available_updates > 0:
657 self.cmdList.append((IpkgComponent.CMD_UPGRADE, { "test_only": False }))
658 if self.selectedFiles and len(self.selectedFiles):
659 for plugin in self.selectedFiles:
660 detailsfile = iSoftwareTools.directory[0] + "/" + plugin[0]
661 if (os_path.exists(detailsfile) == True):
662 iSoftwareTools.fillPackageDetails(plugin[0])
663 self.package = iSoftwareTools.packageDetails[0]
664 if self.package[0].has_key("attributes"):
665 self.attributes = self.package[0]["attributes"]
666 if self.attributes.has_key("package"):
667 self.packagefiles = self.attributes["package"]
668 if plugin[1] == 'installed':
669 if self.packagefiles:
670 for package in self.packagefiles[:]:
671 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package["name"] }))
673 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": plugin[2] }))
675 if self.packagefiles:
676 for package in self.packagefiles[:]:
677 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package["name"] }))
679 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": plugin[2] }))
681 if plugin[1] == 'installed':
682 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": plugin[2] }))
684 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": plugin[2] }))
686 def runExecute(self, result = None):
687 if result is not None:
688 if result[0] is True:
689 self.session.openWithCallback(self.runExecuteFinished, Ipkg, cmdList = self.cmdList)
690 elif result[0] is False:
691 self.cmdList = result[1]
692 self.session.openWithCallback(self.runExecuteFinished, Ipkg, cmdList = self.cmdList)
696 def runExecuteFinished(self):
697 self.session.openWithCallback(self.ExecuteReboot, MessageBox, _("Install or remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
699 def ExecuteReboot(self, result):
703 self.reloadPluginlist()
704 self.selectedFiles = []
705 self.detailsClosed(True)
709 def reloadPluginlist(self):
710 plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
713 class PluginManagerInfo(Screen):
715 <screen name="PluginManagerInfo" position="center,center" size="560,450" title="Plugin manager activity information" >
716 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
717 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
718 <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" />
719 <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" />
720 <widget source="list" render="Listbox" position="5,50" size="550,350" scrollbarMode="showOnDemand" selectionDisabled="1">
721 <convert type="TemplatedMultiContent">
723 MultiContentEntryText(pos = (50, 0), size = (150, 26), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name
724 MultiContentEntryText(pos = (50, 27), size = (540, 23), font=1, flags = RT_HALIGN_LEFT, text = 1), # index 1 is the state
725 MultiContentEntryPixmapAlphaTest(pos = (0, 1), size = (48, 48), png = 2), # index 2 is the status pixmap
726 MultiContentEntryPixmapAlphaTest(pos = (0, 48), size = (550, 2), png = 3), # index 3 is the div pixmap
728 "fonts": [gFont("Regular", 24),gFont("Regular", 22)],
733 <ePixmap pixmap="skin_default/div-h.png" position="0,404" zPosition="10" size="560,2" transparent="1" alphatest="on" />
734 <widget source="status" render="Label" position="5,408" zPosition="10" size="550,44" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
737 def __init__(self, session, plugin_path, cmdlist = None):
738 Screen.__init__(self, session)
739 self.session = session
740 self.skin_path = plugin_path
741 self.cmdlist = cmdlist
743 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
745 "ok": self.process_all,
748 "green": self.process_extensions,
752 self["list"] = List(self.list)
753 self["key_red"] = StaticText(_("Cancel"))
754 self["key_green"] = StaticText(_("Only extensions."))
755 self["status"] = StaticText(_("Following tasks will be done after you press OK!"))
757 self.onShown.append(self.setWindowTitle)
758 self.onLayoutFinish.append(self.rebuildList)
760 def setWindowTitle(self):
761 self.setTitle(_("Plugin manager activity information"))
763 def rebuildList(self):
765 if self.cmdlist is not None:
766 for entry in self.cmdlist:
778 info = args['package']
780 info = args['package']
782 info = _("Dreambox software because updates are available.")
784 self.list.append(self.buildEntryComponent(action,info))
785 self['list'].setList(self.list)
786 self['list'].updateList(self.list)
788 def buildEntryComponent(self, action,info):
789 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png"))
790 upgradepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgrade.png"))
791 installpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/install.png"))
792 removepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png"))
793 if action == 'install':
794 return(( _('Installing'), info, installpng, divpng))
795 elif action == 'remove':
796 return(( _('Removing'), info, removepng, divpng))
798 return(( _('Upgrading'), info, upgradepng, divpng))
803 def process_all(self):
804 self.close((True,None))
806 def process_extensions(self):
808 if self.cmdlist is not None:
809 for entry in self.cmdlist:
811 if entry[0] in (0,2):
812 self.list.append((entry))
813 self.close((False,self.list))
816 class PluginManagerHelp(Screen):
818 <screen name="PluginManagerHelp" position="center,center" size="560,450" title="Plugin manager help" >
819 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
820 <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" />
821 <widget source="list" render="Listbox" position="5,50" size="550,350" scrollbarMode="showOnDemand" selectionDisabled="1">
822 <convert type="TemplatedMultiContent">
824 MultiContentEntryText(pos = (50, 0), size = (540, 26), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name
825 MultiContentEntryText(pos = (50, 27), size = (540, 23), font=1, flags = RT_HALIGN_LEFT, text = 1), # index 1 is the state
826 MultiContentEntryPixmapAlphaTest(pos = (0, 1), size = (48, 48), png = 2), # index 2 is the status pixmap
827 MultiContentEntryPixmapAlphaTest(pos = (0, 48), size = (550, 2), png = 3), # index 3 is the div pixmap
829 "fonts": [gFont("Regular", 24),gFont("Regular", 22)],
834 <ePixmap pixmap="skin_default/div-h.png" position="0,404" zPosition="10" size="560,2" transparent="1" alphatest="on" />
835 <widget source="status" render="Label" position="5,408" zPosition="10" size="550,44" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
838 def __init__(self, session, plugin_path):
839 Screen.__init__(self, session)
840 self.session = session
841 self.skin_path = plugin_path
843 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
850 self["list"] = List(self.list)
851 self["key_red"] = StaticText(_("Close"))
852 self["status"] = StaticText(_("A small overview of the available icon states and actions."))
854 self.onShown.append(self.setWindowTitle)
855 self.onLayoutFinish.append(self.rebuildList)
857 def setWindowTitle(self):
858 self.setTitle(_("Plugin manager help"))
860 def rebuildList(self):
862 self.list.append(self.buildEntryComponent('install'))
863 self.list.append(self.buildEntryComponent('installable'))
864 self.list.append(self.buildEntryComponent('installed'))
865 self.list.append(self.buildEntryComponent('remove'))
866 self['list'].setList(self.list)
867 self['list'].updateList(self.list)
869 def buildEntryComponent(self, state):
870 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png"))
871 installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installed.png"))
872 installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installable.png"))
873 removepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png"))
874 installpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/install.png"))
876 if state == 'installed':
877 return(( _('This plugin is installed.'), _('You can remove this plugin.'), installedpng, divpng))
878 elif state == 'installable':
879 return(( _('This plugin is not installed.'), _('You can install this plugin.'), installablepng, divpng))
880 elif state == 'install':
881 return(( _('This plugin will be installed.'), _('You can cancel the installation.'), installpng, divpng))
882 elif state == 'remove':
883 return(( _('This plugin will be removed.'), _('You can cancel the removal.'), removepng, divpng))
889 class PluginDetails(Screen, DreamInfoHandler):
891 <screen name="PluginDetails" position="center,center" size="600,440" title="Plugin details" >
892 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
893 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
894 <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" />
895 <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" />
896 <widget source="author" render="Label" position="10,50" size="500,25" zPosition="10" font="Regular;21" transparent="1" />
897 <widget name="statuspic" position="550,40" size="48,48" alphatest="on"/>
898 <widget name="divpic" position="0,80" size="600,2" alphatest="on"/>
899 <widget name="detailtext" position="10,90" size="270,330" zPosition="10" font="Regular;21" transparent="1" halign="left" valign="top"/>
900 <widget name="screenshot" position="290,90" size="300,330" alphatest="on"/>
902 def __init__(self, session, plugin_path, packagedata = None):
903 Screen.__init__(self, session)
904 self.skin_path = plugin_path
905 self.language = language.getLanguage()[:2] # getLanguage returns e.g. "fi_FI" for "language_country"
906 self.attributes = None
907 self.translatedAttributes = None
908 DreamInfoHandler.__init__(self, self.statusCallback, blocking = False, language = self.language)
909 self.directory = resolveFilename(SCOPE_METADIR)
911 self.pluginname = packagedata[0]
912 self.details = packagedata[1]
913 self.pluginstate = packagedata[4]
914 self.statuspicinstance = packagedata[5]
915 self.divpicinstance = packagedata[6]
916 self.fillPackageDetails(self.details)
920 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
926 "down": self.pageDown,
928 "right": self.pageDown,
931 self["key_red"] = StaticText(_("Close"))
932 self["key_green"] = StaticText("")
933 self["author"] = StaticText()
934 self["statuspic"] = Pixmap()
935 self["divpic"] = Pixmap()
936 self["screenshot"] = Pixmap()
937 self["detailtext"] = ScrollLabel()
939 self["statuspic"].hide()
940 self["screenshot"].hide()
941 self["divpic"].hide()
943 self.package = self.packageDetails[0]
944 if self.package[0].has_key("attributes"):
945 self.attributes = self.package[0]["attributes"]
946 if self.package[0].has_key("translation"):
947 self.translatedAttributes = self.package[0]["translation"]
950 self.oktext = _("\nAfter pressing OK, please wait!")
951 self.picload = ePicLoad()
952 self.picload.PictureData.get().append(self.paintScreenshotPixmapCB)
953 self.onShown.append(self.setWindowTitle)
954 self.onLayoutFinish.append(self.setInfos)
956 def setWindowTitle(self):
957 self.setTitle(_("Details for extension: " + self.pluginname))
963 self["detailtext"].pageUp()
966 self["detailtext"].pageDown()
968 def statusCallback(self, status, progress):
972 if self.translatedAttributes.has_key("name"):
973 self.pluginname = self.translatedAttributes["name"]
974 elif self.attributes.has_key("name"):
975 self.pluginname = self.attributes["name"]
977 self.pluginname = _("unknown")
979 if self.translatedAttributes.has_key("author"):
980 self.author = self.translatedAttributes["author"]
981 elif self.attributes.has_key("author"):
982 self.author = self.attributes["author"]
984 self.author = _("unknown")
986 if self.translatedAttributes.has_key("description"):
987 self.description = self.translatedAttributes["description"]
988 elif self.attributes.has_key("description"):
989 self.description = self.attributes["description"]
991 self.description = _("No description available.")
993 if self.translatedAttributes.has_key("screenshot"):
994 self.loadThumbnail(self.translatedAttributes)
996 self.loadThumbnail(self.attributes)
998 self["author"].setText(_("Author: ") + self.author)
999 self["detailtext"].setText(self.description.strip())
1000 if self.pluginstate in ('installable', 'install'):
1001 self["key_green"].setText(_("Install"))
1003 self["key_green"].setText(_("Remove"))
1005 def loadThumbnail(self, entry):
1007 if entry.has_key("screenshot"):
1008 thumbnailUrl = entry["screenshot"]
1009 if thumbnailUrl is not None:
1010 self.thumbnail = "/tmp/" + thumbnailUrl.split('/')[-1]
1011 print "[PluginDetails] downloading screenshot " + thumbnailUrl + " to " + self.thumbnail
1012 client.downloadPage(thumbnailUrl,self.thumbnail).addCallback(self.setThumbnail).addErrback(self.fetchFailed)
1014 self.setThumbnail(noScreenshot = True)
1016 def setThumbnail(self, noScreenshot = False):
1017 if not noScreenshot:
1018 filename = self.thumbnail
1020 filename = resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/noprev.png")
1022 sc = AVSwitch().getFramebufferScale()
1023 self.picload.setPara((self["screenshot"].instance.size().width(), self["screenshot"].instance.size().height(), sc[0], sc[1], False, 1, "#00000000"))
1024 self.picload.startDecode(filename)
1026 if self.statuspicinstance != None:
1027 self["statuspic"].instance.setPixmap(self.statuspicinstance.__deref__())
1028 self["statuspic"].show()
1029 if self.divpicinstance != None:
1030 self["divpic"].instance.setPixmap(self.divpicinstance.__deref__())
1031 self["divpic"].show()
1033 def paintScreenshotPixmapCB(self, picInfo=None):
1034 ptr = self.picload.getData()
1036 self["screenshot"].instance.setPixmap(ptr.__deref__())
1037 self["screenshot"].show()
1039 self.setThumbnail(noScreenshot = True)
1042 if self.attributes.has_key("package"):
1043 self.packagefiles = self.attributes["package"]
1045 if self.pluginstate in ('installed', 'remove'):
1046 if self.packagefiles:
1047 for package in self.packagefiles[:]:
1048 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package["name"] }))
1049 if len(self.cmdList):
1050 self.session.openWithCallback(self.runRemove, MessageBox, _("Do you want to remove the package:\n") + self.pluginname + "\n" + self.oktext)
1052 if self.packagefiles:
1053 for package in self.packagefiles[:]:
1054 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package["name"] }))
1055 if len(self.cmdList):
1056 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to install the package:\n") + self.pluginname + "\n" + self.oktext)
1058 def runUpgrade(self, result):
1060 self.session.openWithCallback(self.runUpgradeFinished, Ipkg, cmdList = self.cmdList)
1062 def runUpgradeFinished(self):
1063 self.session.openWithCallback(self.UpgradeReboot, MessageBox, _("Installation finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
1065 def UpgradeReboot(self, result):
1073 def runRemove(self, result):
1075 self.session.openWithCallback(self.runRemoveFinished, Ipkg, cmdList = self.cmdList)
1077 def runRemoveFinished(self):
1078 self.session.openWithCallback(self.RemoveReboot, MessageBox, _("Remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
1080 def RemoveReboot(self, result):
1088 def reloadPluginlist(self):
1089 plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
1091 def fetchFailed(self,string):
1092 self.setThumbnail(noScreenshot = True)
1093 print "[PluginDetails] fetch failed " + string.getErrorMessage()
1096 class UpdatePlugin(Screen):
1098 <screen name="UpdatePlugin" position="center,center" size="550,200" title="Software update" >
1099 <widget name="activityslider" position="0,0" size="550,5" />
1100 <widget name="slider" position="0,150" size="550,30" />
1101 <widget source="package" render="Label" position="10,30" size="540,20" font="Regular;18" halign="center" valign="center" backgroundColor="#25062748" transparent="1" />
1102 <widget source="status" render="Label" position="10,60" size="540,45" font="Regular;20" halign="center" valign="center" backgroundColor="#25062748" transparent="1" />
1105 def __init__(self, session, args = None):
1106 Screen.__init__(self, session)
1108 self.sliderPackages = { "dreambox-dvb-modules": 1, "enigma2": 2, "tuxbox-image-info": 3 }
1110 self.slider = Slider(0, 4)
1111 self["slider"] = self.slider
1112 self.activityslider = Slider(0, 100)
1113 self["activityslider"] = self.activityslider
1114 self.status = StaticText(_("Upgrading Dreambox... Please wait"))
1115 self["status"] = self.status
1116 self.package = StaticText()
1117 self["package"] = self.package
1123 self.activityTimer = eTimer()
1124 self.activityTimer.callback.append(self.doActivityTimer)
1125 self.activityTimer.start(100, False)
1127 self.ipkg = IpkgComponent()
1128 self.ipkg.addCallback(self.ipkgCallback)
1130 self.updating = True
1131 self.package.setText(_("Package list update"))
1132 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
1134 self["actions"] = ActionMap(["WizardActions"],
1140 def doActivityTimer(self):
1142 if self.activity == 100:
1144 self.activityslider.setValue(self.activity)
1146 def ipkgCallback(self, event, param):
1147 if event == IpkgComponent.EVENT_DOWNLOAD:
1148 self.status.setText(_("Downloading"))
1149 elif event == IpkgComponent.EVENT_UPGRADE:
1150 if self.sliderPackages.has_key(param):
1151 self.slider.setValue(self.sliderPackages[param])
1152 self.package.setText(param)
1153 self.status.setText(_("Upgrading"))
1155 elif event == IpkgComponent.EVENT_INSTALL:
1156 self.package.setText(param)
1157 self.status.setText(_("Installing"))
1159 elif event == IpkgComponent.EVENT_CONFIGURING:
1160 self.package.setText(param)
1161 self.status.setText(_("Configuring"))
1162 elif event == IpkgComponent.EVENT_MODIFIED:
1163 self.session.openWithCallback(
1164 self.modificationCallback,
1166 _("A configuration file (%s) was modified since Installation.\nDo you want to keep your version?") % (param)
1168 elif event == IpkgComponent.EVENT_ERROR:
1170 elif event == IpkgComponent.EVENT_DONE:
1172 self.updating = False
1173 self.ipkg.startCmd(IpkgComponent.CMD_UPGRADE, args = {'test_only': False})
1174 elif self.error == 0:
1175 self.slider.setValue(4)
1177 self.activityTimer.stop()
1178 self.activityslider.setValue(0)
1180 self.package.setText("")
1181 self.status.setText(_("Done - Installed or upgraded %d packages") % self.packages)
1183 self.activityTimer.stop()
1184 self.activityslider.setValue(0)
1185 error = _("your dreambox might be unusable now. Please consult the manual for further assistance before rebooting your dreambox.")
1186 if self.packages == 0:
1187 error = _("No packages were upgraded yet. So you can check your network and try again.")
1189 error = _("Your dreambox isn't connected to the internet properly. Please check it and try again.")
1190 self.status.setText(_("Error") + " - " + error)
1191 #print event, "-", param
1194 def modificationCallback(self, res):
1195 self.ipkg.write(res and "N" or "Y")
1198 if not self.ipkg.isRunning():
1199 if self.packages != 0 and self.error == 0:
1200 self.session.openWithCallback(self.exitAnswer, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"))
1204 def exitAnswer(self, result):
1205 if result is not None and result:
1211 class IPKGMenu(Screen):
1213 <screen name="IPKGMenu" position="center,center" size="560,400" title="Select upgrade source to edit." >
1214 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
1215 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
1216 <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" />
1217 <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" />
1218 <widget name="filelist" position="5,50" size="550,340" scrollbarMode="showOnDemand" />
1221 def __init__(self, session, plugin_path):
1222 Screen.__init__(self, session)
1223 self.skin_path = plugin_path
1225 self["key_red"] = StaticText(_("Close"))
1226 self["key_green"] = StaticText(_("Edit"))
1235 self["actions"] = NumberActionMap(["SetupActions"],
1238 "cancel": self.keyCancel
1241 self["shortcuts"] = ActionMap(["ShortcutActions"],
1243 "red": self.keyCancel,
1244 "green": self.KeyOk,
1247 self["filelist"] = MenuList(self.flist)
1249 self.onLayoutFinish.append(self.layoutFinished)
1251 def layoutFinished(self):
1252 self.setWindowTitle()
1254 def setWindowTitle(self):
1255 self.setTitle(_("Select upgrade source to edit."))
1257 def fill_list(self):
1259 self.path = '/etc/ipkg/'
1260 if (os_path.exists(self.path) == False):
1263 for file in listdir(self.path):
1264 if (file.endswith(".conf")):
1265 if file != 'arch.conf':
1266 self.flist.append((file))
1268 self["filelist"].l.setList(self.flist)
1271 if (self.exe == False) and (self.entry == True):
1272 self.sel = self["filelist"].getCurrent()
1273 self.val = self.path + self.sel
1274 self.session.open(IPKGSource, self.val)
1276 def keyCancel(self):
1283 class IPKGSource(Screen):
1285 <screen name="IPKGSource" position="center,center" size="560,80" title="Edit upgrade source url." >
1286 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
1287 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
1288 <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" />
1289 <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" />
1290 <widget name="text" position="5,50" size="550,25" font="Regular;20" backgroundColor="background" foregroundColor="#cccccc" />
1293 def __init__(self, session, configfile = None):
1294 Screen.__init__(self, session)
1295 self.session = session
1296 self.configfile = configfile
1300 fp = file(configfile, 'r')
1301 sources = fp.readlines()
1308 desk = getDesktop(0)
1309 x= int(desk.size().width())
1310 y= int(desk.size().height())
1312 self["key_red"] = StaticText(_("Cancel"))
1313 self["key_green"] = StaticText(_("Save"))
1316 self["text"] = Input(text, maxSize=False, type=Input.TEXT)
1318 self["text"] = Input(text, maxSize=False, visible_width = 55, type=Input.TEXT)
1320 self["actions"] = NumberActionMap(["WizardActions", "InputActions", "TextEntryActions", "KeyboardInputActions","ShortcutActions"],
1326 "left": self.keyLeft,
1327 "right": self.keyRight,
1328 "home": self.keyHome,
1330 "deleteForward": self.keyDeleteForward,
1331 "deleteBackward": self.keyDeleteBackward,
1332 "1": self.keyNumberGlobal,
1333 "2": self.keyNumberGlobal,
1334 "3": self.keyNumberGlobal,
1335 "4": self.keyNumberGlobal,
1336 "5": self.keyNumberGlobal,
1337 "6": self.keyNumberGlobal,
1338 "7": self.keyNumberGlobal,
1339 "8": self.keyNumberGlobal,
1340 "9": self.keyNumberGlobal,
1341 "0": self.keyNumberGlobal
1344 self.onLayoutFinish.append(self.layoutFinished)
1346 def layoutFinished(self):
1347 self.setWindowTitle()
1348 self["text"].right()
1350 def setWindowTitle(self):
1351 self.setTitle(_("Edit upgrade source url."))
1354 text = self["text"].getText()
1356 fp = file(self.configfile, 'w')
1366 self["text"].right()
1374 def keyDeleteForward(self):
1375 self["text"].delete()
1377 def keyDeleteBackward(self):
1378 self["text"].deleteBackward()
1380 def keyNumberGlobal(self, number):
1381 self["text"].number(number)
1384 class PacketManager(Screen):
1386 <screen name="PacketManager" position="center,center" size="530,420" title="Packet manager" >
1387 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
1388 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
1389 <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" />
1390 <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" />
1391 <widget source="list" render="Listbox" position="5,50" size="520,365" scrollbarMode="showOnDemand">
1392 <convert type="TemplatedMultiContent">
1394 MultiContentEntryText(pos = (5, 1), size = (440, 28), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name
1395 MultiContentEntryText(pos = (5, 26), size = (440, 20), font=1, flags = RT_HALIGN_LEFT, text = 2), # index 2 is the description
1396 MultiContentEntryPixmapAlphaTest(pos = (445, 2), size = (48, 48), png = 4), # index 4 is the status pixmap
1397 MultiContentEntryPixmapAlphaTest(pos = (5, 50), size = (510, 2), png = 5), # index 4 is the div pixmap
1399 "fonts": [gFont("Regular", 22),gFont("Regular", 14)],
1406 def __init__(self, session, plugin_path, args = None):
1407 Screen.__init__(self, session)
1408 self.session = session
1409 self.skin_path = plugin_path
1411 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
1416 "green": self.reload,
1420 self.statuslist = []
1421 self["list"] = List(self.list)
1422 self["key_red"] = StaticText(_("Close"))
1423 self["key_green"] = StaticText(_("Reload"))
1425 self.list_updating = True
1426 self.packetlist = []
1427 self.installed_packetlist = {}
1428 self.Console = Console()
1431 self.cache_ttl = 86400 #600 is default, 0 disables, Seconds cache is considered valid (24h should be ok for caching ipkgs)
1432 self.cache_file = '/usr/lib/enigma2/python/Plugins/SystemPlugins/SoftwareManager/packetmanager.cache' #Path to cache directory
1433 self.oktext = _("\nAfter pressing OK, please wait!")
1434 self.unwanted_extensions = ('-dbg', '-dev', '-doc', 'busybox')
1436 self.ipkg = IpkgComponent()
1437 self.ipkg.addCallback(self.ipkgCallback)
1438 self.onShown.append(self.setWindowTitle)
1439 self.onLayoutFinish.append(self.rebuildList)
1443 if self.Console is not None:
1444 if len(self.Console.appContainers):
1445 for name in self.Console.appContainers.keys():
1446 self.Console.kill(name)
1450 if (os_path.exists(self.cache_file) == True):
1451 remove(self.cache_file)
1452 self.list_updating = True
1455 def setWindowTitle(self):
1456 self.setTitle(_("Packet manager"))
1458 def setStatus(self,status = None):
1460 self.statuslist = []
1461 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png"))
1462 if status == 'update':
1463 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgrade.png"))
1464 self.statuslist.append(( _("Package list update"), '', _("Trying to download a new packetlist. Please wait..." ),'',statuspng, divpng ))
1465 self['list'].setList(self.statuslist)
1466 elif status == 'error':
1467 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png"))
1468 self.statuslist.append(( _("Error"), '', _("There was an error downloading the packetlist. Please try again." ),'',statuspng, divpng ))
1469 self['list'].setList(self.statuslist)
1471 def rebuildList(self):
1472 self.setStatus('update')
1474 self.vc = valid_cache(self.cache_file, self.cache_ttl)
1475 if self.cache_ttl > 0 and self.vc != 0:
1477 self.buildPacketList()
1480 if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0:
1482 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
1484 def go(self, returnValue = None):
1485 cur = self["list"].getCurrent()
1490 if status == 'installed':
1491 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package }))
1492 if len(self.cmdList):
1493 self.session.openWithCallback(self.runRemove, MessageBox, _("Do you want to remove the package:\n") + package + "\n" + self.oktext)
1494 elif status == 'upgradeable':
1495 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package }))
1496 if len(self.cmdList):
1497 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to upgrade the package:\n") + package + "\n" + self.oktext)
1498 elif status == "installable":
1499 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package }))
1500 if len(self.cmdList):
1501 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to install the package:\n") + package + "\n" + self.oktext)
1503 def runRemove(self, result):
1505 self.session.openWithCallback(self.runRemoveFinished, Ipkg, cmdList = self.cmdList)
1507 def runRemoveFinished(self):
1508 self.session.openWithCallback(self.RemoveReboot, MessageBox, _("Remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
1510 def RemoveReboot(self, result):
1514 cur = self["list"].getCurrent()
1516 item = self['list'].getIndex()
1517 self.list[item] = self.buildEntryComponent(cur[0], cur[1], cur[2], 'installable')
1518 self.cachelist[item] = [cur[0], cur[1], cur[2], 'installable']
1519 self['list'].setList(self.list)
1520 write_cache(self.cache_file, self.cachelist)
1521 self.reloadPluginlist()
1525 def runUpgrade(self, result):
1527 self.session.openWithCallback(self.runUpgradeFinished, Ipkg, cmdList = self.cmdList)
1529 def runUpgradeFinished(self):
1530 self.session.openWithCallback(self.UpgradeReboot, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
1532 def UpgradeReboot(self, result):
1536 cur = self["list"].getCurrent()
1538 item = self['list'].getIndex()
1539 self.list[item] = self.buildEntryComponent(cur[0], cur[1], cur[2], 'installed')
1540 self.cachelist[item] = [cur[0], cur[1], cur[2], 'installed']
1541 self['list'].setList(self.list)
1542 write_cache(self.cache_file, self.cachelist)
1543 self.reloadPluginlist()
1547 def ipkgCallback(self, event, param):
1548 if event == IpkgComponent.EVENT_ERROR:
1549 self.list_updating = False
1550 self.setStatus('error')
1551 elif event == IpkgComponent.EVENT_DONE:
1552 if self.list_updating:
1553 self.list_updating = False
1554 if not self.Console:
1555 self.Console = Console()
1557 self.Console.ePopen(cmd, self.IpkgList_Finished)
1558 #print event, "-", param
1561 def IpkgList_Finished(self, result, retval, extra_args = None):
1563 self.packetlist = []
1564 for x in result.splitlines():
1565 tokens = x.split(' - ') #self.blacklisted_packages
1566 name = tokens[0].strip()
1567 if not any(name.endswith(x) for x in self.unwanted_extensions):
1569 version = l > 1 and tokens[1].strip() or ""
1570 descr = l > 2 and tokens[2].strip() or ""
1571 self.packetlist.append([name, version, descr])
1572 if not self.Console:
1573 self.Console = Console()
1574 cmd = "ipkg list_installed"
1575 self.Console.ePopen(cmd, self.IpkgListInstalled_Finished)
1577 def IpkgListInstalled_Finished(self, result, retval, extra_args = None):
1579 self.installed_packetlist = {}
1580 for x in result.splitlines():
1581 tokens = x.split(' - ') #self.blacklisted_packages
1582 name = tokens[0].strip()
1583 if not any(name.endswith(x) for x in self.unwanted_extensions):
1585 version = l > 1 and tokens[1].strip() or ""
1586 self.installed_packetlist[name] = version
1587 self.buildPacketList()
1589 def buildEntryComponent(self, name, version, description, state):
1590 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png"))
1591 if state == 'installed':
1592 installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installed.png"))
1593 return((name, version, description, state, installedpng, divpng))
1594 elif state == 'upgradeable':
1595 upgradeablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgradeable.png"))
1596 return((name, version, description, state, upgradeablepng, divpng))
1598 installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installable.png"))
1599 return((name, version, description, state, installablepng, divpng))
1601 def buildPacketList(self):
1605 if self.cache_ttl > 0 and self.vc != 0:
1606 print 'Loading packagelist cache from ',self.cache_file
1608 self.cachelist = load_cache(self.cache_file)
1609 if len(self.cachelist) > 0:
1610 for x in self.cachelist:
1611 self.list.append(self.buildEntryComponent(x[0], x[1], x[2], x[3]))
1612 self['list'].setList(self.list)
1616 if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0:
1617 print 'rebuilding fresh package list'
1618 for x in self.packetlist:
1620 if self.installed_packetlist.has_key(x[0].strip()):
1621 if self.installed_packetlist[x[0].strip()] == x[1].strip():
1622 status = "installed"
1623 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status))
1625 status = "upgradeable"
1626 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status))
1628 status = "installable"
1629 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status))
1630 if not any(x[0].strip().endswith(x) for x in self.unwanted_extensions):
1631 self.cachelist.append([x[0].strip(), x[1].strip(), x[2].strip(), status])
1632 write_cache(self.cache_file, self.cachelist)
1633 self['list'].setList(self.list)
1635 def reloadPluginlist(self):
1636 plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
1638 class IpkgInstaller(Screen):
1640 <screen name="IpkgInstaller" position="center,center" size="550,450" title="Install extensions" >
1641 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
1642 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
1643 <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" />
1644 <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" />
1645 <widget name="list" position="5,50" size="540,360" />
1646 <ePixmap pixmap="skin_default/div-h.png" position="0,410" zPosition="10" size="560,2" transparent="1" alphatest="on" />
1647 <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" />
1650 def __init__(self, session, list):
1651 Screen.__init__(self, session)
1653 self.list = SelectionList()
1654 self["list"] = self.list
1655 for listindex in range(len(list)):
1656 self.list.addSelection(list[listindex], list[listindex], listindex, True)
1658 self["key_red"] = StaticText(_("Close"))
1659 self["key_green"] = StaticText(_("Install"))
1660 self["introduction"] = StaticText(_("Press OK to toggle the selection."))
1662 self["actions"] = ActionMap(["OkCancelActions", "ColorActions"],
1664 "ok": self.list.toggleSelection,
1665 "cancel": self.close,
1667 "green": self.install
1671 list = self.list.getSelectionsList()
1674 cmdList.append((IpkgComponent.CMD_INSTALL, { "package": item[1] }))
1675 self.session.open(Ipkg, cmdList = cmdList)
1678 def filescan_open(list, session, **kwargs):
1679 filelist = [x.path for x in list]
1680 session.open(IpkgInstaller, filelist) # list
1682 def filescan(**kwargs):
1683 from Components.Scanner import Scanner, ScanPath
1685 Scanner(mimetypes = ["application/x-debian-package"],
1688 ScanPath(path = "ipk", with_subdirs = True),
1689 ScanPath(path = "", with_subdirs = False),
1692 description = _("Install extensions."),
1693 openfnc = filescan_open, )
1697 def UpgradeMain(session, **kwargs):
1698 session.open(UpdatePluginMenu)
1700 def startSetup(menuid):
1701 if menuid != "setup":
1703 return [(_("Software management"), UpgradeMain, "software_manager", 50)]
1706 def Plugins(path, **kwargs):
1710 PluginDescriptor(name=_("Software management"), description=_("Manage your receiver's software"), where = PluginDescriptor.WHERE_MENU, fnc=startSetup),
1711 PluginDescriptor(name=_("Ipkg"), where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)
1713 if config.usage.setup_level.index >= 2: # expert+
1714 list.append(PluginDescriptor(name=_("Software management"), description=_("Manage your receiver's software"), where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc=UpgradeMain))