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 = (0, 1), size = (470, 24), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name
311 MultiContentEntryText(pos = (0, 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 elif status == 'sync':
409 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgrade.png"))
410 self.statuslist.append(( _("Package list update"), '', _("Searching for new installed or removed packages. Please wait..." ),'', '', statuspng, divpng, None, '' ))
411 elif status == 'error':
412 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png"))
413 self.statuslist.append(( _("Error"), '', _("There was an error downloading the packetlist. Please try again." ),'', '', statuspng, divpng, None, '' ))
414 self["list"].style = "default"
415 self['list'].setList(self.statuslist)
418 def getUpdateInfos(self):
419 self.setState('update')
420 iSoftwareTools.startSoftwareTools(self.getUpdateInfosCB)
422 def getUpdateInfosCB(self, retval = None):
423 if retval is not None:
425 if iSoftwareTools.available_updates is not 0:
426 self["status"].setText(_("There are at least ") + str(iSoftwareTools.available_updates) + _(" updates available."))
428 self["status"].setText(_("There are no updates available."))
430 elif retval is False:
431 self.setState('error')
432 if iSoftwareTools.NetworkConnectionAvailable:
433 self["status"].setText(_("Updatefeed not available."))
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 DreamInfoHandler.__init__(self, self.statusCallback, blocking = False)
908 self.directory = resolveFilename(SCOPE_METADIR)
910 self.pluginname = packagedata[0]
911 self.details = packagedata[1]
912 self.pluginstate = packagedata[4]
913 self.statuspicinstance = packagedata[5]
914 self.divpicinstance = packagedata[6]
915 self.fillPackageDetails(self.details)
919 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
925 "down": self.pageDown,
927 "right": self.pageDown,
930 self["key_red"] = StaticText(_("Close"))
931 self["key_green"] = StaticText("")
932 self["author"] = StaticText()
933 self["statuspic"] = Pixmap()
934 self["divpic"] = Pixmap()
935 self["screenshot"] = Pixmap()
936 self["detailtext"] = ScrollLabel()
938 self["statuspic"].hide()
939 self["screenshot"].hide()
940 self["divpic"].hide()
942 self.package = self.packageDetails[0]
943 if self.package[0].has_key("attributes"):
944 self.attributes = self.package[0]["attributes"]
947 self.oktext = _("\nAfter pressing OK, please wait!")
948 self.picload = ePicLoad()
949 self.picload.PictureData.get().append(self.paintScreenshotPixmapCB)
950 self.onShown.append(self.setWindowTitle)
951 self.onLayoutFinish.append(self.setInfos)
953 def setWindowTitle(self):
954 self.setTitle(_("Details for plugin: ") + self.pluginname )
960 self["detailtext"].pageUp()
963 self["detailtext"].pageDown()
965 def statusCallback(self, status, progress):
969 if self.attributes.has_key("screenshot"):
970 self.loadThumbnail(self.attributes)
972 if self.attributes.has_key("name"):
973 self.pluginname = self.attributes["name"]
975 self.pluginname = _("unknown")
977 if self.attributes.has_key("author"):
978 self.author = self.attributes["author"]
980 self.author = _("unknown")
982 if self.attributes.has_key("description"):
983 self.description = _(self.attributes["description"].replace("\\n", "\n"))
985 self.description = _("No description available.")
987 self["author"].setText(_("Author: ") + self.author)
988 self["detailtext"].setText(_(self.description))
989 if self.pluginstate in ('installable', 'install'):
990 self["key_green"].setText(_("Install"))
992 self["key_green"].setText(_("Remove"))
994 def loadThumbnail(self, entry):
996 if entry.has_key("screenshot"):
997 thumbnailUrl = entry["screenshot"]
998 if self.language == "de":
999 if thumbnailUrl[-7:] == "_en.jpg":
1000 thumbnailUrl = thumbnailUrl[:-7] + "_de.jpg"
1002 if thumbnailUrl is not None:
1003 self.thumbnail = "/tmp/" + thumbnailUrl.split('/')[-1]
1004 print "[PluginDetails] downloading screenshot " + thumbnailUrl + " to " + self.thumbnail
1005 client.downloadPage(thumbnailUrl,self.thumbnail).addCallback(self.setThumbnail).addErrback(self.fetchFailed)
1007 self.setThumbnail(noScreenshot = True)
1009 def setThumbnail(self, noScreenshot = False):
1010 if not noScreenshot:
1011 filename = self.thumbnail
1013 filename = resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/noprev.png")
1015 sc = AVSwitch().getFramebufferScale()
1016 self.picload.setPara((self["screenshot"].instance.size().width(), self["screenshot"].instance.size().height(), sc[0], sc[1], False, 1, "#00000000"))
1017 self.picload.startDecode(filename)
1019 if self.statuspicinstance != None:
1020 self["statuspic"].instance.setPixmap(self.statuspicinstance.__deref__())
1021 self["statuspic"].show()
1022 if self.divpicinstance != None:
1023 self["divpic"].instance.setPixmap(self.divpicinstance.__deref__())
1024 self["divpic"].show()
1026 def paintScreenshotPixmapCB(self, picInfo=None):
1027 ptr = self.picload.getData()
1029 self["screenshot"].instance.setPixmap(ptr.__deref__())
1030 self["screenshot"].show()
1032 self.setThumbnail(noScreenshot = True)
1035 if self.attributes.has_key("package"):
1036 self.packagefiles = self.attributes["package"]
1038 if self.pluginstate in ('installed', 'remove'):
1039 if self.packagefiles:
1040 for package in self.packagefiles[:]:
1041 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package["name"] }))
1042 if len(self.cmdList):
1043 self.session.openWithCallback(self.runRemove, MessageBox, _("Do you want to remove the package:\n") + self.pluginname + "\n" + self.oktext)
1045 if self.packagefiles:
1046 for package in self.packagefiles[:]:
1047 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package["name"] }))
1048 if len(self.cmdList):
1049 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to install the package:\n") + self.pluginname + "\n" + self.oktext)
1051 def runUpgrade(self, result):
1053 self.session.openWithCallback(self.runUpgradeFinished, Ipkg, cmdList = self.cmdList)
1055 def runUpgradeFinished(self):
1056 self.session.openWithCallback(self.UpgradeReboot, MessageBox, _("Installation finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
1058 def UpgradeReboot(self, result):
1066 def runRemove(self, result):
1068 self.session.openWithCallback(self.runRemoveFinished, Ipkg, cmdList = self.cmdList)
1070 def runRemoveFinished(self):
1071 self.session.openWithCallback(self.RemoveReboot, MessageBox, _("Remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
1073 def RemoveReboot(self, result):
1081 def reloadPluginlist(self):
1082 plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
1084 def fetchFailed(self,string):
1085 self.setThumbnail(noScreenshot = True)
1086 print "[PluginDetails] fetch failed " + string.getErrorMessage()
1089 class UpdatePlugin(Screen):
1091 <screen name="UpdatePlugin" position="center,center" size="550,200" title="Software update" >
1092 <widget name="activityslider" position="0,0" size="550,5" />
1093 <widget name="slider" position="0,150" size="550,30" />
1094 <widget source="package" render="Label" position="10,30" size="540,20" font="Regular;18" halign="center" valign="center" backgroundColor="#25062748" transparent="1" />
1095 <widget source="status" render="Label" position="10,60" size="540,45" font="Regular;20" halign="center" valign="center" backgroundColor="#25062748" transparent="1" />
1098 def __init__(self, session, args = None):
1099 Screen.__init__(self, session)
1101 self.sliderPackages = { "dreambox-dvb-modules": 1, "enigma2": 2, "tuxbox-image-info": 3 }
1103 self.slider = Slider(0, 4)
1104 self["slider"] = self.slider
1105 self.activityslider = Slider(0, 100)
1106 self["activityslider"] = self.activityslider
1107 self.status = StaticText(_("Upgrading Dreambox... Please wait"))
1108 self["status"] = self.status
1109 self.package = StaticText()
1110 self["package"] = self.package
1116 self.activityTimer = eTimer()
1117 self.activityTimer.callback.append(self.doActivityTimer)
1118 self.activityTimer.start(100, False)
1120 self.ipkg = IpkgComponent()
1121 self.ipkg.addCallback(self.ipkgCallback)
1123 self.updating = True
1124 self.package.setText(_("Package list update"))
1125 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
1127 self["actions"] = ActionMap(["WizardActions"],
1133 def doActivityTimer(self):
1135 if self.activity == 100:
1137 self.activityslider.setValue(self.activity)
1139 def ipkgCallback(self, event, param):
1140 if event == IpkgComponent.EVENT_DOWNLOAD:
1141 self.status.setText(_("Downloading"))
1142 elif event == IpkgComponent.EVENT_UPGRADE:
1143 if self.sliderPackages.has_key(param):
1144 self.slider.setValue(self.sliderPackages[param])
1145 self.package.setText(param)
1146 self.status.setText(_("Upgrading"))
1148 elif event == IpkgComponent.EVENT_INSTALL:
1149 self.package.setText(param)
1150 self.status.setText(_("Installing"))
1152 elif event == IpkgComponent.EVENT_CONFIGURING:
1153 self.package.setText(param)
1154 self.status.setText(_("Configuring"))
1155 elif event == IpkgComponent.EVENT_MODIFIED:
1156 self.session.openWithCallback(
1157 self.modificationCallback,
1159 _("A configuration file (%s) was modified since Installation.\nDo you want to keep your version?") % (param)
1161 elif event == IpkgComponent.EVENT_ERROR:
1163 elif event == IpkgComponent.EVENT_DONE:
1165 self.updating = False
1166 self.ipkg.startCmd(IpkgComponent.CMD_UPGRADE, args = {'test_only': False})
1167 elif self.error == 0:
1168 self.slider.setValue(4)
1170 self.activityTimer.stop()
1171 self.activityslider.setValue(0)
1173 self.package.setText("")
1174 self.status.setText(_("Done - Installed or upgraded %d packages") % self.packages)
1176 self.activityTimer.stop()
1177 self.activityslider.setValue(0)
1178 error = _("your dreambox might be unusable now. Please consult the manual for further assistance before rebooting your dreambox.")
1179 if self.packages == 0:
1180 error = _("No packages were upgraded yet. So you can check your network and try again.")
1182 error = _("Your dreambox isn't connected to the internet properly. Please check it and try again.")
1183 self.status.setText(_("Error") + " - " + error)
1184 #print event, "-", param
1187 def modificationCallback(self, res):
1188 self.ipkg.write(res and "N" or "Y")
1191 if not self.ipkg.isRunning():
1192 if self.packages != 0 and self.error == 0:
1193 self.session.openWithCallback(self.exitAnswer, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"))
1197 def exitAnswer(self, result):
1198 if result is not None and result:
1204 class IPKGMenu(Screen):
1206 <screen name="IPKGMenu" position="center,center" size="560,400" title="Select upgrade source to edit." >
1207 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
1208 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
1209 <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" />
1210 <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" />
1211 <widget name="filelist" position="5,50" size="550,340" scrollbarMode="showOnDemand" />
1214 def __init__(self, session, plugin_path):
1215 Screen.__init__(self, session)
1216 self.skin_path = plugin_path
1218 self["key_red"] = StaticText(_("Close"))
1219 self["key_green"] = StaticText(_("Edit"))
1228 self["actions"] = NumberActionMap(["SetupActions"],
1231 "cancel": self.keyCancel
1234 self["shortcuts"] = ActionMap(["ShortcutActions"],
1236 "red": self.keyCancel,
1237 "green": self.KeyOk,
1240 self["filelist"] = MenuList(self.flist)
1242 self.onLayoutFinish.append(self.layoutFinished)
1244 def layoutFinished(self):
1245 self.setWindowTitle()
1247 def setWindowTitle(self):
1248 self.setTitle(_("Select upgrade source to edit."))
1250 def fill_list(self):
1252 self.path = '/etc/ipkg/'
1253 if (os_path.exists(self.path) == False):
1256 for file in listdir(self.path):
1257 if (file.endswith(".conf")):
1258 if file != 'arch.conf':
1259 self.flist.append((file))
1261 self["filelist"].l.setList(self.flist)
1264 if (self.exe == False) and (self.entry == True):
1265 self.sel = self["filelist"].getCurrent()
1266 self.val = self.path + self.sel
1267 self.session.open(IPKGSource, self.val)
1269 def keyCancel(self):
1276 class IPKGSource(Screen):
1278 <screen name="IPKGSource" position="center,center" size="560,80" title="Edit upgrade source url." >
1279 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
1280 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
1281 <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" />
1282 <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" />
1283 <widget name="text" position="5,50" size="550,25" font="Regular;20" backgroundColor="background" foregroundColor="#cccccc" />
1286 def __init__(self, session, configfile = None):
1287 Screen.__init__(self, session)
1288 self.session = session
1289 self.configfile = configfile
1293 fp = file(configfile, 'r')
1294 sources = fp.readlines()
1301 desk = getDesktop(0)
1302 x= int(desk.size().width())
1303 y= int(desk.size().height())
1305 self["key_red"] = StaticText(_("Cancel"))
1306 self["key_green"] = StaticText(_("Save"))
1309 self["text"] = Input(text, maxSize=False, type=Input.TEXT)
1311 self["text"] = Input(text, maxSize=False, visible_width = 55, type=Input.TEXT)
1313 self["actions"] = NumberActionMap(["WizardActions", "InputActions", "TextEntryActions", "KeyboardInputActions","ShortcutActions"],
1319 "left": self.keyLeft,
1320 "right": self.keyRight,
1321 "home": self.keyHome,
1323 "deleteForward": self.keyDeleteForward,
1324 "deleteBackward": self.keyDeleteBackward,
1325 "1": self.keyNumberGlobal,
1326 "2": self.keyNumberGlobal,
1327 "3": self.keyNumberGlobal,
1328 "4": self.keyNumberGlobal,
1329 "5": self.keyNumberGlobal,
1330 "6": self.keyNumberGlobal,
1331 "7": self.keyNumberGlobal,
1332 "8": self.keyNumberGlobal,
1333 "9": self.keyNumberGlobal,
1334 "0": self.keyNumberGlobal
1337 self.onLayoutFinish.append(self.layoutFinished)
1339 def layoutFinished(self):
1340 self.setWindowTitle()
1341 self["text"].right()
1343 def setWindowTitle(self):
1344 self.setTitle(_("Edit upgrade source url."))
1347 text = self["text"].getText()
1349 fp = file(self.configfile, 'w')
1359 self["text"].right()
1367 def keyDeleteForward(self):
1368 self["text"].delete()
1370 def keyDeleteBackward(self):
1371 self["text"].deleteBackward()
1373 def keyNumberGlobal(self, number):
1374 self["text"].number(number)
1377 class PacketManager(Screen):
1379 <screen name="PacketManager" position="center,center" size="530,420" title="Packet manager" >
1380 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
1381 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
1382 <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" />
1383 <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" />
1384 <widget source="list" render="Listbox" position="5,50" size="520,365" scrollbarMode="showOnDemand">
1385 <convert type="TemplatedMultiContent">
1387 MultiContentEntryText(pos = (5, 1), size = (440, 28), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name
1388 MultiContentEntryText(pos = (5, 26), size = (440, 20), font=1, flags = RT_HALIGN_LEFT, text = 2), # index 2 is the description
1389 MultiContentEntryPixmapAlphaTest(pos = (445, 2), size = (48, 48), png = 4), # index 4 is the status pixmap
1390 MultiContentEntryPixmapAlphaTest(pos = (5, 50), size = (510, 2), png = 5), # index 4 is the div pixmap
1392 "fonts": [gFont("Regular", 22),gFont("Regular", 14)],
1399 def __init__(self, session, plugin_path, args = None):
1400 Screen.__init__(self, session)
1401 self.session = session
1402 self.skin_path = plugin_path
1404 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
1409 "green": self.reload,
1413 self.statuslist = []
1414 self["list"] = List(self.list)
1415 self["key_red"] = StaticText(_("Close"))
1416 self["key_green"] = StaticText(_("Reload"))
1418 self.list_updating = True
1419 self.packetlist = []
1420 self.installed_packetlist = {}
1421 self.Console = Console()
1424 self.cache_ttl = 86400 #600 is default, 0 disables, Seconds cache is considered valid (24h should be ok for caching ipkgs)
1425 self.cache_file = '/usr/lib/enigma2/python/Plugins/SystemPlugins/SoftwareManager/packetmanager.cache' #Path to cache directory
1426 self.oktext = _("\nAfter pressing OK, please wait!")
1427 self.unwanted_extensions = ('-dbg', '-dev', '-doc', 'busybox')
1429 self.ipkg = IpkgComponent()
1430 self.ipkg.addCallback(self.ipkgCallback)
1431 self.onShown.append(self.setWindowTitle)
1432 self.onLayoutFinish.append(self.rebuildList)
1436 if self.Console is not None:
1437 if len(self.Console.appContainers):
1438 for name in self.Console.appContainers.keys():
1439 self.Console.kill(name)
1443 if (os_path.exists(self.cache_file) == True):
1444 remove(self.cache_file)
1445 self.list_updating = True
1448 def setWindowTitle(self):
1449 self.setTitle(_("Packet manager"))
1451 def setStatus(self,status = None):
1453 self.statuslist = []
1454 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png"))
1455 if status == 'update':
1456 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgrade.png"))
1457 self.statuslist.append(( _("Package list update"), '', _("Trying to download a new packetlist. Please wait..." ),'',statuspng, divpng ))
1458 self['list'].setList(self.statuslist)
1459 elif status == 'error':
1460 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png"))
1461 self.statuslist.append(( _("Error"), '', _("There was an error downloading the packetlist. Please try again." ),'',statuspng, divpng ))
1462 self['list'].setList(self.statuslist)
1464 def rebuildList(self):
1465 self.setStatus('update')
1467 self.vc = valid_cache(self.cache_file, self.cache_ttl)
1468 if self.cache_ttl > 0 and self.vc != 0:
1470 self.buildPacketList()
1473 if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0:
1475 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
1477 def go(self, returnValue = None):
1478 cur = self["list"].getCurrent()
1483 if status == 'installed':
1484 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package }))
1485 if len(self.cmdList):
1486 self.session.openWithCallback(self.runRemove, MessageBox, _("Do you want to remove the package:\n") + package + "\n" + self.oktext)
1487 elif status == 'upgradeable':
1488 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package }))
1489 if len(self.cmdList):
1490 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to upgrade the package:\n") + package + "\n" + self.oktext)
1491 elif status == "installable":
1492 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package }))
1493 if len(self.cmdList):
1494 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to install the package:\n") + package + "\n" + self.oktext)
1496 def runRemove(self, result):
1498 self.session.openWithCallback(self.runRemoveFinished, Ipkg, cmdList = self.cmdList)
1500 def runRemoveFinished(self):
1501 self.session.openWithCallback(self.RemoveReboot, MessageBox, _("Remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
1503 def RemoveReboot(self, result):
1507 cur = self["list"].getCurrent()
1509 item = self['list'].getIndex()
1510 self.list[item] = self.buildEntryComponent(cur[0], cur[1], cur[2], 'installable')
1511 self.cachelist[item] = [cur[0], cur[1], cur[2], 'installable']
1512 self['list'].setList(self.list)
1513 write_cache(self.cache_file, self.cachelist)
1514 self.reloadPluginlist()
1518 def runUpgrade(self, result):
1520 self.session.openWithCallback(self.runUpgradeFinished, Ipkg, cmdList = self.cmdList)
1522 def runUpgradeFinished(self):
1523 self.session.openWithCallback(self.UpgradeReboot, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
1525 def UpgradeReboot(self, result):
1529 cur = self["list"].getCurrent()
1531 item = self['list'].getIndex()
1532 self.list[item] = self.buildEntryComponent(cur[0], cur[1], cur[2], 'installed')
1533 self.cachelist[item] = [cur[0], cur[1], cur[2], 'installed']
1534 self['list'].setList(self.list)
1535 write_cache(self.cache_file, self.cachelist)
1536 self.reloadPluginlist()
1540 def ipkgCallback(self, event, param):
1541 if event == IpkgComponent.EVENT_ERROR:
1542 self.list_updating = False
1543 self.setStatus('error')
1544 elif event == IpkgComponent.EVENT_DONE:
1545 if self.list_updating:
1546 self.list_updating = False
1547 if not self.Console:
1548 self.Console = Console()
1550 self.Console.ePopen(cmd, self.IpkgList_Finished)
1551 #print event, "-", param
1554 def IpkgList_Finished(self, result, retval, extra_args = None):
1556 self.packetlist = []
1557 for x in result.splitlines():
1558 tokens = x.split(' - ') #self.blacklisted_packages
1559 name = tokens[0].strip()
1560 if not any(name.endswith(x) for x in self.unwanted_extensions):
1562 version = l > 1 and tokens[1].strip() or ""
1563 descr = l > 2 and tokens[2].strip() or ""
1564 self.packetlist.append([name, version, descr])
1565 if not self.Console:
1566 self.Console = Console()
1567 cmd = "ipkg list_installed"
1568 self.Console.ePopen(cmd, self.IpkgListInstalled_Finished)
1570 def IpkgListInstalled_Finished(self, result, retval, extra_args = None):
1572 self.installed_packetlist = {}
1573 for x in result.splitlines():
1574 tokens = x.split(' - ') #self.blacklisted_packages
1575 name = tokens[0].strip()
1576 if not any(name.endswith(x) for x in self.unwanted_extensions):
1578 version = l > 1 and tokens[1].strip() or ""
1579 self.installed_packetlist[name] = version
1580 self.buildPacketList()
1582 def buildEntryComponent(self, name, version, description, state):
1583 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png"))
1584 if state == 'installed':
1585 installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installed.png"))
1586 return((name, version, description, state, installedpng, divpng))
1587 elif state == 'upgradeable':
1588 upgradeablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgradeable.png"))
1589 return((name, version, description, state, upgradeablepng, divpng))
1591 installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installable.png"))
1592 return((name, version, description, state, installablepng, divpng))
1594 def buildPacketList(self):
1598 if self.cache_ttl > 0 and self.vc != 0:
1599 print 'Loading packagelist cache from ',self.cache_file
1601 self.cachelist = load_cache(self.cache_file)
1602 if len(self.cachelist) > 0:
1603 for x in self.cachelist:
1604 self.list.append(self.buildEntryComponent(x[0], x[1], x[2], x[3]))
1605 self['list'].setList(self.list)
1609 if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0:
1610 print 'rebuilding fresh package list'
1611 for x in self.packetlist:
1613 if self.installed_packetlist.has_key(x[0].strip()):
1614 if self.installed_packetlist[x[0].strip()] == x[1].strip():
1615 status = "installed"
1616 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status))
1618 status = "upgradeable"
1619 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status))
1621 status = "installable"
1622 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status))
1623 if not any(x[0].strip().endswith(x) for x in self.unwanted_extensions):
1624 self.cachelist.append([x[0].strip(), x[1].strip(), x[2].strip(), status])
1625 write_cache(self.cache_file, self.cachelist)
1626 self['list'].setList(self.list)
1628 def reloadPluginlist(self):
1629 plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
1631 class IpkgInstaller(Screen):
1633 <screen name="IpkgInstaller" position="center,center" size="550,450" title="Install extensions" >
1634 <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
1635 <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
1636 <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" />
1637 <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" />
1638 <widget name="list" position="5,50" size="540,360" />
1639 <ePixmap pixmap="skin_default/div-h.png" position="0,410" zPosition="10" size="560,2" transparent="1" alphatest="on" />
1640 <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" />
1643 def __init__(self, session, list):
1644 Screen.__init__(self, session)
1646 self.list = SelectionList()
1647 self["list"] = self.list
1648 for listindex in range(len(list)):
1649 self.list.addSelection(list[listindex], list[listindex], listindex, True)
1651 self["key_red"] = StaticText(_("Close"))
1652 self["key_green"] = StaticText(_("Install"))
1653 self["introduction"] = StaticText(_("Press OK to toggle the selection."))
1655 self["actions"] = ActionMap(["OkCancelActions", "ColorActions"],
1657 "ok": self.list.toggleSelection,
1658 "cancel": self.close,
1660 "green": self.install
1664 list = self.list.getSelectionsList()
1667 cmdList.append((IpkgComponent.CMD_INSTALL, { "package": item[1] }))
1668 self.session.open(Ipkg, cmdList = cmdList)
1671 def filescan_open(list, session, **kwargs):
1672 filelist = [x.path for x in list]
1673 session.open(IpkgInstaller, filelist) # list
1675 def filescan(**kwargs):
1676 from Components.Scanner import Scanner, ScanPath
1678 Scanner(mimetypes = ["application/x-debian-package"],
1681 ScanPath(path = "ipk", with_subdirs = True),
1682 ScanPath(path = "", with_subdirs = False),
1685 description = _("Install extensions."),
1686 openfnc = filescan_open, )
1690 def UpgradeMain(session, **kwargs):
1691 session.open(UpdatePluginMenu)
1693 def startSetup(menuid):
1694 if menuid != "setup":
1696 return [(_("Software management"), UpgradeMain, "software_manager", 50)]
1699 def Plugins(path, **kwargs):
1703 PluginDescriptor(name=_("Software management"), description=_("Manage your receiver's software"), where = PluginDescriptor.WHERE_MENU, fnc=startSetup),
1704 PluginDescriptor(name=_("Ipkg"), where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)
1706 if config.usage.setup_level.index >= 2: # expert+
1707 list.append(PluginDescriptor(name=_("Software management"), description=_("Manage your receiver's software"), where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc=UpgradeMain))