From: Stefan Pluecken Date: Tue, 5 Jan 2010 13:42:23 +0000 (+0100) Subject: Merge branch 'master' of git.opendreambox.org:/git/enigma2 X-Git-Tag: 2.7.0~1^2~2 X-Git-Url: https://git.cweiske.de/enigma2.git/commitdiff_plain/c92c4778f26f253b4a2869ffaf4c89cbf090e66d?hp=a415c30723058b3da1c7cbc1adf7c2205508915b Merge branch 'master' of git.opendreambox.org:/git/enigma2 --- diff --git a/data/skin_default/Makefile.am b/data/skin_default/Makefile.am old mode 100644 new mode 100755 index 3106af97..9e9b7cd4 --- a/data/skin_default/Makefile.am +++ b/data/skin_default/Makefile.am @@ -15,6 +15,7 @@ dist_install_DATA = \ border_eventinfo.png \ border_info.png \ border_menu_300.png \ + border_menu_350.png \ border_menu.png \ border_multiepg.png \ bottombar.png \ diff --git a/data/skin_default/border_menu_350.png b/data/skin_default/border_menu_350.png new file mode 100755 index 00000000..4f6f49c2 Binary files /dev/null and b/data/skin_default/border_menu_350.png differ diff --git a/data/skin_default/div-h.png b/data/skin_default/div-h.png old mode 100644 new mode 100755 index d6fcc7fb..9ab4ff45 Binary files a/data/skin_default/div-h.png and b/data/skin_default/div-h.png differ diff --git a/lib/python/Components/config.py b/lib/python/Components/config.py index a6007b10..471b59ec 100755 --- a/lib/python/Components/config.py +++ b/lib/python/Components/config.py @@ -1138,6 +1138,9 @@ class ConfigDirectory(ConfigText): else: return ConfigText.getMulti(self, selected) + def onSelect(self, session): + self.allmarked = (self.value != "") + # a slider. class ConfigSlider(ConfigElement): def __init__(self, default = 0, increment = 1, limits = (0, 100)): diff --git a/lib/python/Plugins/Extensions/DVDBurn/Process.py b/lib/python/Plugins/Extensions/DVDBurn/Process.py index 44075d64..642a898d 100644 --- a/lib/python/Plugins/Extensions/DVDBurn/Process.py +++ b/lib/python/Plugins/Extensions/DVDBurn/Process.py @@ -264,6 +264,7 @@ class WaitForResidentTasks(Task): def run(self, callback): print "waiting for %d resident task(s) %s to finish..." % (len(self.job.resident_tasks),str(self.job.resident_tasks)) + self.callback = callback if self.job.resident_tasks == 0: callback(self, []) diff --git a/lib/python/Plugins/Extensions/DVDBurn/ProjectSettings.py b/lib/python/Plugins/Extensions/DVDBurn/ProjectSettings.py index c4289cb0..a1c38842 100755 --- a/lib/python/Plugins/Extensions/DVDBurn/ProjectSettings.py +++ b/lib/python/Plugins/Extensions/DVDBurn/ProjectSettings.py @@ -8,7 +8,6 @@ from Components.Sources.List import List from Components.Sources.StaticText import StaticText from Components.Sources.Progress import Progress from Components.FileList import FileList -from enigma import eListboxPythonMultiContent, gFont, RT_HALIGN_LEFT from Tools.Directories import fileExists, resolveFilename, SCOPE_PLUGINS, SCOPE_FONTS, SCOPE_HDD from Components.config import config, getConfigListEntry from Components.ConfigList import ConfigListScreen @@ -235,7 +234,6 @@ class ProjectSettings(Screen,ConfigListScreen): self.session.open(MessageBox,self.project.error,MessageBox.TYPE_ERROR) elif scope == "project": if self.project.loadProject(path): - configRef.setValue(path) self.initConfigList() else: self.session.open(MessageBox,self.project.error,MessageBox.TYPE_ERROR) diff --git a/lib/python/Plugins/Extensions/DVDBurn/TitleList.py b/lib/python/Plugins/Extensions/DVDBurn/TitleList.py index 928a8b82..dbc988b1 100755 --- a/lib/python/Plugins/Extensions/DVDBurn/TitleList.py +++ b/lib/python/Plugins/Extensions/DVDBurn/TitleList.py @@ -10,7 +10,8 @@ from Components.ActionMap import HelpableActionMap, ActionMap from Components.Sources.List import List from Components.Sources.StaticText import StaticText from Components.Sources.Progress import Progress -from enigma import eListboxPythonMultiContent, gFont, RT_HALIGN_LEFT +from Components.MultiContent import MultiContentEntryText +from enigma import gFont, RT_HALIGN_LEFT, RT_HALIGN_RIGHT from Tools.Directories import resolveFilename, SCOPE_PLUGINS class TitleList(Screen, HelpableScreen): @@ -27,7 +28,18 @@ class TitleList(Screen, HelpableScreen): - + + {"template": [ + MultiContentEntryText(pos = (0, 0), size = (420, 20), font = 0, flags = RT_HALIGN_LEFT, text = 1), # index 1 Title, + MultiContentEntryText(pos = (0, 20), size = (328, 17), font = 1, flags = RT_HALIGN_LEFT, text = 2), # index 2 description, + MultiContentEntryText(pos = (420, 6), size = (120, 20), font = 1, flags = RT_HALIGN_RIGHT, text = 3), # index 3 begin time, + MultiContentEntryText(pos = (328, 20), size = (154, 17), font = 1, flags = RT_HALIGN_RIGHT, text = 4), # index 4 channel, + MultiContentEntryText(pos = (482, 20), size = (58, 20), font = 1, flags = RT_HALIGN_RIGHT, text = 5), # index 4 channel, + ], + "fonts": [gFont("Regular", 20), gFont("Regular", 14)], + "itemHeight": 37 + } + @@ -71,7 +83,7 @@ class TitleList(Screen, HelpableScreen): else: self.newProject() - self["titles"] = List(list = [ ], enableWrapAround = True, item_height=30, fonts = [gFont("Regular", 20)]) + self["titles"] = List([]) self.updateTitleList() self.previous_size = 0 self.onLayoutFinish.append(self.layoutFinished) @@ -188,6 +200,9 @@ class TitleList(Screen, HelpableScreen): def selectedSource(self, source): if source is None: return None + if not source.getPath().endswith(".ts"): + self.session.open(MessageBox,text = _("You can only burn Dreambox recordings!"), type = MessageBox.TYPE_ERROR) + return None t = self.project.addService(source) try: editor = source.edit @@ -256,15 +271,14 @@ class TitleList(Screen, HelpableScreen): job = Process.DVDJob(self.project, menupreview=True) job_manager.in_background = False job_manager.AddJob(job) - + def updateTitleList(self): - res = [ ] + list = [ ] for title in self.project.titles: - a = [ title, (eListboxPythonMultiContent.TYPE_TEXT, 0, 5, 500, 25, 0, RT_HALIGN_LEFT, title.properties.menutitle.getValue()) ] - res.append(a) - self["titles"].list = res + list.append((title, title.properties.menutitle.getValue(), title.properties.menusubtitle.getValue(), title.DVBchannel, title.formatDVDmenuText("$D.$M.$Y, $T", 0), title.formatDVDmenuText("$l", 0))) + self["titles"].list = list self.updateSize() - if len(res): + if len(list): self["key_red"].text = _("Remove title") self["key_yellow"].text = _("Title properties") else: diff --git a/lib/python/Plugins/Extensions/DVDBurn/TitleProperties.py b/lib/python/Plugins/Extensions/DVDBurn/TitleProperties.py index 11601cc3..0a664eba 100755 --- a/lib/python/Plugins/Extensions/DVDBurn/TitleProperties.py +++ b/lib/python/Plugins/Extensions/DVDBurn/TitleProperties.py @@ -9,7 +9,7 @@ from Components.Sources.StaticText import StaticText from Components.Sources.Progress import Progress from Components.FileList import FileList from Components.Pixmap import Pixmap -from enigma import eListboxPythonMultiContent, gFont, RT_HALIGN_LEFT, ePicLoad +from enigma import ePicLoad from Tools.Directories import fileExists, resolveFilename, SCOPE_PLUGINS, SCOPE_FONTS, SCOPE_HDD from Components.config import config, getConfigListEntry, ConfigInteger, ConfigSubsection, ConfigSelection from Components.ConfigList import ConfigListScreen @@ -164,7 +164,8 @@ class LanguageChoices(): self.choices.sort() self.choices.insert(0,("nolang", ("unspecified"))) self.choices.insert(1,(syslang, self.langdict[syslang])) - self.choices.insert(2,("en", self.langdict["en"])) + if syslang != "en": + self.choices.insert(2,("en", self.langdict["en"])) def getLanguage(self, DVB_lang): DVB_lang = DVB_lang.lower() diff --git a/lib/python/Plugins/Extensions/DVDPlayer/src/servicedvd.cpp b/lib/python/Plugins/Extensions/DVDPlayer/src/servicedvd.cpp index 94f2ee38..0372c497 100644 --- a/lib/python/Plugins/Extensions/DVDPlayer/src/servicedvd.cpp +++ b/lib/python/Plugins/Extensions/DVDPlayer/src/servicedvd.cpp @@ -696,7 +696,7 @@ RESULT eServiceDVD::setTrickmode(int /*trick*/) RESULT eServiceDVD::isCurrentlySeekable() { - return m_state == stRunning; + return m_state == stRunning ? 3 : 0; } RESULT eServiceDVD::keyPressed(int key) diff --git a/lib/python/Plugins/SystemPlugins/SoftwareManager/Makefile.am b/lib/python/Plugins/SystemPlugins/SoftwareManager/Makefile.am old mode 100644 new mode 100755 index ee1e56de..2d5e3381 --- a/lib/python/Plugins/SystemPlugins/SoftwareManager/Makefile.am +++ b/lib/python/Plugins/SystemPlugins/SoftwareManager/Makefile.am @@ -6,7 +6,8 @@ install_PYTHON = \ __init__.py \ plugin.py \ BackupRestore.py \ - ImageWizard.py + ImageWizard.py \ + SoftwareTools.py dist_install_DATA = \ imagewizard.xml \ diff --git a/lib/python/Plugins/SystemPlugins/SoftwareManager/SoftwareTools.py b/lib/python/Plugins/SystemPlugins/SoftwareManager/SoftwareTools.py new file mode 100755 index 00000000..4e7591ef --- /dev/null +++ b/lib/python/Plugins/SystemPlugins/SoftwareManager/SoftwareTools.py @@ -0,0 +1,226 @@ +from enigma import eConsoleAppContainer +from Components.Console import Console +from Components.About import about +from Components.DreamInfoHandler import DreamInfoHandler +from Components.Language import language +from Components.Sources.List import List +from Components.Ipkg import IpkgComponent +from Components.Network import iNetwork +from Tools.Directories import pathExists, fileExists, resolveFilename, SCOPE_METADIR + +from time import time + +class SoftwareTools(DreamInfoHandler): + lastDownloadDate = None + NetworkConnectionAvailable = None + list_updating = False + available_updates = 0 + available_updatelist = [] + available_packetlist = [] + installed_packetlist = {} + + + def __init__(self): + aboutInfo = about.getImageVersionString() + if aboutInfo.startswith("dev-"): + self.ImageVersion = 'Experimental' + else: + self.ImageVersion = 'Stable' + self.language = language.getLanguage()[:2] # getLanguage returns e.g. "fi_FI" for "language_country" + DreamInfoHandler.__init__(self, self.statusCallback, blocking = False, neededTag = 'ALL_TAGS', neededFlag = self.ImageVersion, language = self.language) + self.directory = resolveFilename(SCOPE_METADIR) + self.list = List([]) + self.NotifierCallback = None + self.Console = Console() + self.UpdateConsole = Console() + self.cmdList = [] + self.unwanted_extensions = ('-dbg', '-dev', '-doc') + self.ipkg = IpkgComponent() + self.ipkg.addCallback(self.ipkgCallback) + + def statusCallback(self, status, progress): + pass + + def startSoftwareTools(self, callback = None): + if callback is not None: + self.NotifierCallback = callback + iNetwork.checkNetworkState(self.checkNetworkCB) + + def checkNetworkCB(self,data): + if data is not None: + if data <= 2: + SoftwareTools.NetworkConnectionAvailable = True + self.getUpdates() + else: + SoftwareTools.NetworkConnectionAvailable = False + self.getUpdates() + + def getUpdates(self, callback = None): + if SoftwareTools.NetworkConnectionAvailable == True: + SoftwareTools.lastDownloadDate = time() + if SoftwareTools.list_updating is False and callback is None: + SoftwareTools.list_updating = True + self.ipkg.startCmd(IpkgComponent.CMD_UPDATE) + elif SoftwareTools.list_updating is False and callback is not None: + SoftwareTools.list_updating = True + self.NotifierCallback = callback + self.ipkg.startCmd(IpkgComponent.CMD_UPDATE) + elif SoftwareTools.list_updating is True and callback is not None: + #update info collecting already in progress + self.NotifierCallback = callback + else: + SoftwareTools.list_updating = False + if callback is not None: + callback(False) + elif self.NotifierCallback is not None: + self.NotifierCallback(False) + + def ipkgCallback(self, event, param): + if event == IpkgComponent.EVENT_ERROR: + SoftwareTools.list_updating = False + elif event == IpkgComponent.EVENT_DONE: + if SoftwareTools.list_updating: + self.startIpkgListAvailable() + pass + + def startIpkgListAvailable(self, callback = None): + if callback is not None: + SoftwareTools.list_updating = True + if SoftwareTools.list_updating: + if not self.UpdateConsole: + self.UpdateConsole = Console() + cmd = "ipkg list" + self.UpdateConsole.ePopen(cmd, self.IpkgListAvailableCB, callback) + + def IpkgListAvailableCB(self, result, retval, extra_args = None): + (callback) = extra_args + if len(result): + if SoftwareTools.list_updating: + SoftwareTools.available_packetlist = [] + for x in result.splitlines(): + split = x.split(' - ') + name = split[0].strip() + if not any(name.endswith(x) for x in self.unwanted_extensions): + SoftwareTools.available_packetlist.append([name, split[1].strip(), split[2].strip()]) + if callback is None: + self.startInstallMetaPackage() + else: + if self.UpdateConsole: + if len(self.UpdateConsole.appContainers) == 0: + callback(True) + else: + SoftwareTools.list_updating = False + if self.UpdateConsole: + if len(self.UpdateConsole.appContainers) == 0: + if callback is not None: + callback(False) + + def startInstallMetaPackage(self, callback = None): + if callback is not None: + SoftwareTools.list_updating = True + if SoftwareTools.list_updating: + if not self.UpdateConsole: + self.UpdateConsole = Console() + cmd = "ipkg install enigma2-meta enigma2-plugins-meta enigma2-skins-meta" + self.UpdateConsole.ePopen(cmd, self.InstallMetaPackageCB, callback) + + def InstallMetaPackageCB(self, result, retval, extra_args = None): + (callback) = extra_args + if len(result): + self.fillPackagesIndexList() + if callback is None: + self.startIpkgListInstalled() + else: + if self.UpdateConsole: + if len(self.UpdateConsole.appContainers) == 0: + callback(True) + else: + SoftwareTools.list_updating = False + if self.UpdateConsole: + if len(self.UpdateConsole.appContainers) == 0: + if callback is not None: + callback(False) + + def startIpkgListInstalled(self, callback = None): + if callback is not None: + SoftwareTools.list_updating = True + if SoftwareTools.list_updating: + if not self.UpdateConsole: + self.UpdateConsole = Console() + cmd = "ipkg list_installed" + self.UpdateConsole.ePopen(cmd, self.IpkgListInstalledCB, callback) + + def IpkgListInstalledCB(self, result, retval, extra_args = None): + (callback) = extra_args + if len(result): + SoftwareTools.installed_packetlist = {} + for x in result.splitlines(): + split = x.split(' - ') + name = split[0].strip() + if not any(name.endswith(x) for x in self.unwanted_extensions): + SoftwareTools.installed_packetlist[name] = split[1].strip() + if callback is None: + self.countUpdates() + else: + if self.UpdateConsole: + if len(self.UpdateConsole.appContainers) == 0: + callback(True) + else: + SoftwareTools.list_updating = False + if self.UpdateConsole: + if len(self.UpdateConsole.appContainers) == 0: + if callback is not None: + callback(False) + + def countUpdates(self, callback = None): + SoftwareTools.available_updates = 0 + SoftwareTools.available_updatelist = [] + for package in self.packagesIndexlist[:]: + attributes = package[0]["attributes"] + packagename = attributes["packagename"] + for x in SoftwareTools.available_packetlist: + if x[0] == packagename: + if SoftwareTools.installed_packetlist.has_key(packagename): + if SoftwareTools.installed_packetlist[packagename] != x[1]: + SoftwareTools.available_updates +=1 + SoftwareTools.available_updatelist.append([packagename]) + + SoftwareTools.list_updating = False + if self.UpdateConsole: + if len(self.UpdateConsole.appContainers) == 0: + if callback is not None: + callback(True) + callback = None + elif self.NotifierCallback is not None: + self.NotifierCallback(True) + self.NotifierCallback = None + + def startIpkgUpdate(self, callback = None): + if not self.Console: + self.Console = Console() + cmd = "ipkg update" + self.Console.ePopen(cmd, self.IpkgUpdateCB, callback) + + def IpkgUpdateCB(self, result, retval, extra_args = None): + (callback) = extra_args + if len(result): + if self.Console: + if len(self.Console.appContainers) == 0: + if callback is not None: + callback(True) + callback = None + + def cleanupSoftwareTools(self): + if self.NotifierCallback is not None: + self.NotifierCallback = None + self.ipkg.stop() + if self.Console is not None: + if len(self.Console.appContainers): + for name in self.Console.appContainers.keys(): + self.Console.kill(name) + if self.UpdateConsole is not None: + if len(self.UpdateConsole.appContainers): + for name in self.UpdateConsole.appContainers.keys(): + self.UpdateConsole.kill(name) + +iSoftwareTools = SoftwareTools() \ No newline at end of file diff --git a/lib/python/Plugins/SystemPlugins/SoftwareManager/plugin.py b/lib/python/Plugins/SystemPlugins/SoftwareManager/plugin.py index c70201b3..f61ea53c 100755 --- a/lib/python/Plugins/SystemPlugins/SoftwareManager/plugin.py +++ b/lib/python/Plugins/SystemPlugins/SoftwareManager/plugin.py @@ -23,6 +23,7 @@ from Components.About import about from Components.DreamInfoHandler import DreamInfoHandler from Components.Language import language from Components.AVSwitch import AVSwitch +from Components.Network import iNetwork from Tools.Directories import pathExists, fileExists, resolveFilename, SCOPE_PLUGINS, SCOPE_CURRENT_PLUGIN, SCOPE_CURRENT_SKIN, SCOPE_METADIR from Tools.LoadPixmap import LoadPixmap from enigma import eTimer, quitMainloop, RT_HALIGN_LEFT, RT_VALIGN_CENTER, eListboxPythonMultiContent, eListbox, gFont, getDesktop, ePicLoad @@ -36,6 +37,7 @@ from twisted.internet import reactor from ImageWizard import ImageWizard from BackupRestore import BackupSelection, RestoreMenu, BackupScreen, RestoreScreen, getBackupPath, getBackupFilename +from SoftwareTools import iSoftwareTools config.plugins.configurationbackup = ConfigSubsection() config.plugins.configurationbackup.backuplocation = ConfigText(default = '/media/hdd/', visible_width = 50, fixed_size = False) @@ -74,30 +76,31 @@ def load_cache(cache_file): class UpdatePluginMenu(Screen): skin = """ - + - - + + {"template": [ - MultiContentEntryText(pos = (2, 2), size = (290, 22), flags = RT_HALIGN_LEFT, text = 1), # index 0 is the MenuText, + MultiContentEntryText(pos = (2, 2), size = (330, 24), flags = RT_HALIGN_LEFT, text = 1), # index 0 is the MenuText, ], - "fonts": [gFont("Regular", 20)], + "fonts": [gFont("Regular", 22)], "itemHeight": 25 } - + {"template": [ MultiContentEntryText(pos = (2, 2), size = (240, 300), flags = RT_HALIGN_CENTER|RT_VALIGN_CENTER|RT_WRAP, text = 2), # index 2 is the Description, ], - "fonts": [gFont("Regular", 20)], + "fonts": [gFont("Regular", 22)], "itemHeight": 300 } + """ def __init__(self, session, args = 0): @@ -106,14 +109,15 @@ class UpdatePluginMenu(Screen): self.menu = args self.list = [] self.oktext = _("\nPress OK on your remote control to continue.") + self.text = "" self.backupdirs = ' '.join( config.plugins.configurationbackup.backupdirs.value ) if self.menu == 0: + self.list.append(("install-extensions", _("Manage extensions"), _("\nManage extensions or plugins for your Dreambox" ) + self.oktext, None)) self.list.append(("software-update", _("Software update"), _("\nOnline update of your Dreambox software." ) + self.oktext, None)) - #self.list.append(("install-plugins", _("Install extensions"), _("\nInstall new Extensions or Plugins to your dreambox" ) + self.oktext, None)) self.list.append(("software-restore", _("Software restore"), _("\nRestore your Dreambox with a new firmware." ) + self.oktext, None)) self.list.append(("system-backup", _("Backup system settings"), _("\nBackup your Dreambox settings." ) + self.oktext, None)) self.list.append(("system-restore",_("Restore system settings"), _("\nRestore your Dreambox settings." ) + self.oktext, None)) - self.list.append(("ipkg-install", _("Install local extension"), _("\nScan for local packages and install them." ) + self.oktext, None)) + self.list.append(("ipkg-install", _("Install local extension"), _("\nScan for local extensions and install them." ) + self.oktext, None)) for p in plugins.getPlugins(PluginDescriptor.WHERE_SOFTWAREMANAGER): if p.__call__.has_key("SoftwareSupported"): callFnc = p.__call__["SoftwareSupported"](None) @@ -133,8 +137,8 @@ class UpdatePluginMenu(Screen): self.list.append(("advancedrestore", _("Advanced restore"), _("\nRestore your backups by date." ) + self.oktext, None)) self.list.append(("backuplocation", _("Choose backup location"), _("\nSelect your backup device.\nCurrent device: " ) + config.plugins.configurationbackup.backuplocation.value + self.oktext, None)) self.list.append(("backupfiles", _("Choose backup files"), _("Select files for backup. Currently selected:\n" ) + self.backupdirs + self.oktext, None)) - if config.usage.setup_level.index >= 2: # expert+ - self.list.append(("ipkg-manager", _("Packet management"), _("\nView, install and remove available or installed packages." ) + self.oktext, None)) + #if config.usage.setup_level.index >= 2: # expert+ + # self.list.append(("ipkg-manager", _("Packet management"), _("\nView, install and remove available or installed packages." ) + self.oktext, None)) self.list.append(("ipkg-source",_("Choose upgrade source"), _("\nEdit the upgrade source address." ) + self.oktext, None)) for p in plugins.getPlugins(PluginDescriptor.WHERE_SOFTWAREMANAGER): if p.__call__.has_key("AdvancedSoftwareSupported"): @@ -152,28 +156,54 @@ class UpdatePluginMenu(Screen): self["menu"] = List(self.list) self["key_red"] = StaticText(_("Close")) + self["status"] = StaticText("") - self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"], + self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions", "InfobarEPGActions"], { "ok": self.go, "back": self.close, "red": self.close, }, -1) - self.onLayoutFinish.append(self.layoutFinished) self.backuppath = getBackupPath() self.backupfile = getBackupFilename() self.fullbackupfilename = self.backuppath + "/" + self.backupfile self.onShown.append(self.setWindowTitle) + #self.onClose.append(self.cleanup) def layoutFinished(self): idx = 0 self["menu"].index = idx + #self.getUpdateInfos() def setWindowTitle(self): - self.setTitle(_("Software manager")) + self.setTitle(_("Software management")) + + def cleanup(self): + iNetwork.stopPingConsole() + iSoftwareTools.cleanupSoftwareTools() + + def getUpdateInfos(self): + self.text = "" + if iSoftwareTools.NetworkConnectionAvailable == True: + if iSoftwareTools.list_updating is False: + if iSoftwareTools.available_updates is not 0: + self.text = _("There are at least ") + str(iSoftwareTools.available_updates) + _(" updates available.") + else: + self.text = "" #_("There are no updates available.") + else: + if iSoftwareTools.available_updates is not 0: + self.text = _("There are at least ") + str(iSoftwareTools.available_updates) + _(" updates available.") + else: + self.text = "" #_("There are no updates available.") + self.text += "\n" + _("A search for available updates is currently in progress.") + else: + self.text = _("No network connection available.") + self["status"].setText(self.text) + def go(self): + #iNetwork.stopPingConsole() current = self["menu"].getCurrent() if current: currentEntry = current[0] @@ -182,7 +212,7 @@ class UpdatePluginMenu(Screen): self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to update your Dreambox?")+"\n"+_("\nAfter pressing OK, please wait!")) elif (currentEntry == "software-restore"): self.session.open(ImageWizard) - elif (currentEntry == "install-plugins"): + elif (currentEntry == "install-extensions"): self.session.open(PluginManager, self.skin_path) elif (currentEntry == "system-backup"): self.session.openWithCallback(self.backupDone,BackupScreen, runBackup = True) @@ -260,1262 +290,1212 @@ class UpdatePluginMenu(Screen): self.exe = True self.session.open(RestoreScreen, runRestore = True) -class IPKGMenu(Screen): - skin = """ - - - - - - - """ - - def __init__(self, session, plugin_path): - Screen.__init__(self, session) - self.skin_path = plugin_path - - self["key_red"] = StaticText(_("Close")) - self["key_green"] = StaticText(_("Edit")) - - self.sel = [] - self.val = [] - self.entry = False - self.exe = False - - self.path = "" - - self["actions"] = NumberActionMap(["SetupActions"], - { - "ok": self.KeyOk, - "cancel": self.keyCancel - }, -1) - - self["shortcuts"] = ActionMap(["ShortcutActions"], - { - "red": self.keyCancel, - "green": self.KeyOk, - }) - self.flist = [] - self["filelist"] = MenuList(self.flist) - self.fill_list() - self.onLayoutFinish.append(self.layoutFinished) - - def layoutFinished(self): - self.setWindowTitle() - - def setWindowTitle(self): - self.setTitle(_("Select upgrade source to edit.")) - - def fill_list(self): - self.flist = [] - self.path = '/etc/ipkg/' - if (os_path.exists(self.path) == False): - self.entry = False - return - for file in listdir(self.path): - if (file.endswith(".conf")): - if file != 'arch.conf': - self.flist.append((file)) - self.entry = True - self["filelist"].l.setList(self.flist) - - def KeyOk(self): - if (self.exe == False) and (self.entry == True): - self.sel = self["filelist"].getCurrent() - self.val = self.path + self.sel - self.session.open(IPKGSource, self.val) - - def keyCancel(self): - self.close() - - def Exit(self): - self.close() - - -class IPKGSource(Screen): - skin = """ - - - - - - - """ - - def __init__(self, session, configfile = None): - Screen.__init__(self, session) - self.session = session - self.configfile = configfile - text = "" - if self.configfile: - try: - fp = file(configfile, 'r') - sources = fp.readlines() - if sources: - text = sources[0] - fp.close() - except IOError: - pass - - desk = getDesktop(0) - x= int(desk.size().width()) - y= int(desk.size().height()) - - self["key_red"] = StaticText(_("Cancel")) - self["key_green"] = StaticText(_("Save")) - - if (y>=720): - self["text"] = Input(text, maxSize=False, type=Input.TEXT) - else: - self["text"] = Input(text, maxSize=False, visible_width = 55, type=Input.TEXT) - - self["actions"] = NumberActionMap(["WizardActions", "InputActions", "TextEntryActions", "KeyboardInputActions","ShortcutActions"], - { - "ok": self.go, - "back": self.close, - "red": self.close, - "green": self.go, - "left": self.keyLeft, - "right": self.keyRight, - "home": self.keyHome, - "end": self.keyEnd, - "deleteForward": self.keyDeleteForward, - "deleteBackward": self.keyDeleteBackward, - "1": self.keyNumberGlobal, - "2": self.keyNumberGlobal, - "3": self.keyNumberGlobal, - "4": self.keyNumberGlobal, - "5": self.keyNumberGlobal, - "6": self.keyNumberGlobal, - "7": self.keyNumberGlobal, - "8": self.keyNumberGlobal, - "9": self.keyNumberGlobal, - "0": self.keyNumberGlobal - }, -1) - - self.onLayoutFinish.append(self.layoutFinished) - - def layoutFinished(self): - self.setWindowTitle() - self["text"].right() - - def setWindowTitle(self): - self.setTitle(_("Edit upgrade source url.")) - - def go(self): - text = self["text"].getText() - if text: - fp = file(self.configfile, 'w') - fp.write(text) - fp.write("\n") - fp.close() - self.close() - - def keyLeft(self): - self["text"].left() - - def keyRight(self): - self["text"].right() - - def keyHome(self): - self["text"].home() - - def keyEnd(self): - self["text"].end() - - def keyDeleteForward(self): - self["text"].delete() - - def keyDeleteBackward(self): - self["text"].deleteBackward() - - def keyNumberGlobal(self, number): - self["text"].number(number) +class PluginManager(Screen, DreamInfoHandler): -class PacketManager(Screen): skin = """ - + + + - + + + - {"template": [ - MultiContentEntryText(pos = (5, 1), size = (440, 28), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name - MultiContentEntryText(pos = (5, 26), size = (440, 20), font=1, flags = RT_HALIGN_LEFT, text = 2), # index 2 is the description - MultiContentEntryPixmapAlphaTest(pos = (445, 2), size = (48, 48), png = 4), # index 4 is the status pixmap - MultiContentEntryPixmapAlphaTest(pos = (5, 50), size = (510, 2), png = 5), # index 4 is the div pixmap - ], - "fonts": [gFont("Regular", 22),gFont("Regular", 14)], + {"templates": + {"default": (51,[ + MultiContentEntryText(pos = (30, 1), size = (470, 24), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name + MultiContentEntryText(pos = (30, 25), size = (470, 24), font=1, flags = RT_HALIGN_LEFT, text = 2), # index 2 is the description + MultiContentEntryPixmapAlphaTest(pos = (475, 0), size = (48, 48), png = 5), # index 5 is the status pixmap + MultiContentEntryPixmapAlphaTest(pos = (0, 49), size = (550, 2), png = 6), # index 6 is the div pixmap + ]), + "category": (40,[ + MultiContentEntryText(pos = (30, 0), size = (500, 22), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name + MultiContentEntryText(pos = (30, 22), size = (500, 16), font=2, flags = RT_HALIGN_LEFT, text = 1), # index 1 is the description + MultiContentEntryPixmapAlphaTest(pos = (0, 38), size = (550, 2), png = 3), # index 3 is the div pixmap + ]) + }, + "fonts": [gFont("Regular", 22),gFont("Regular", 20),gFont("Regular", 16)], "itemHeight": 52 - } + } + """ - + def __init__(self, session, plugin_path, args = None): Screen.__init__(self, session) self.session = session self.skin_path = plugin_path - self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"], + self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions", "InfobarEPGActions", "HelpActions" ], { - "ok": self.go, + "ok": self.handleCurrent, "back": self.exit, "red": self.exit, - "green": self.reload, + "green": self.handleCurrent, + "yellow": self.handleSelected, + "showEventInfo": self.handleSelected, + "displayHelp": self.handleHelp, }, -1) - + self.list = [] self.statuslist = [] + self.selectedFiles = [] + self.categoryList = [] + self.packetlist = [] self["list"] = List(self.list) self["key_red"] = StaticText(_("Close")) - self["key_green"] = StaticText(_("Reload")) + self["key_green"] = StaticText("") + self["key_yellow"] = StaticText("") + self["key_blue"] = StaticText("") + self["status"] = StaticText("") - self.list_updating = True - self.packetlist = [] - self.installed_packetlist = {} - self.Console = Console() self.cmdList = [] - self.cachelist = [] - self.cache_ttl = 86400 #600 is default, 0 disables, Seconds cache is considered valid (24h should be ok for caching ipkgs) - self.cache_file = '/usr/lib/enigma2/python/Plugins/SystemPlugins/SoftwareManager/packetmanager.cache' #Path to cache directory self.oktext = _("\nAfter pressing OK, please wait!") - self.unwanted_extensions = ('-dbg', '-dev', '-doc', 'busybox') + if not self.selectionChanged in self["list"].onSelectionChanged: + self["list"].onSelectionChanged.append(self.selectionChanged) - self.ipkg = IpkgComponent() - self.ipkg.addCallback(self.ipkgCallback) + self.currList = "" + self.currentSelectedTag = None + self.currentSelectedIndex = None + self.currentSelectedPackage = None + self.saved_currentSelectedPackage = None + self.onShown.append(self.setWindowTitle) - self.onLayoutFinish.append(self.rebuildList) + self.onLayoutFinish.append(self.getUpdateInfos) - def exit(self): - self.ipkg.stop() - if self.Console is not None: - if len(self.Console.appContainers): - for name in self.Console.appContainers.keys(): - self.Console.kill(name) - self.close() + def setWindowTitle(self): + self.setTitle(_("Extensions management")) - def reload(self): - if (os_path.exists(self.cache_file) == True): - remove(self.cache_file) - self.list_updating = True - self.rebuildList() - - def setWindowTitle(self): - self.setTitle(_("Packet manager")) + def exit(self): + if self.currList == "packages": + self.currList = "category" + self.currentSelectedTag = None + self["list"].style = "category" + self['list'].setList(self.categoryList) + self["list"].setIndex(self.currentSelectedIndex) + self["list"].updateList(self.categoryList) + self.selectionChanged() + else: + iSoftwareTools.cleanupSoftwareTools() + self.prepareInstall() + if len(self.cmdList): + self.session.openWithCallback(self.runExecute, PluginManagerInfo, self.skin_path, self.cmdList) + else: + self.close() - def setStatus(self,status = None): + def handleHelp(self): + if self.currList != "status": + self.session.open(PluginManagerHelp, self.skin_path) + + def setState(self,status = None): if status: + self.currList = "status" self.statuslist = [] + self["key_green"].setText("") + self["key_blue"].setText("") + self["key_yellow"].setText("") divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png")) if status == 'update': statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgrade.png")) - self.statuslist.append(( _("Package list update"), '', _("Trying to download a new packetlist. Please wait..." ),'',statuspng, divpng )) - self['list'].setList(self.statuslist) + self.statuslist.append(( _("Updating software catalog"), '', _("Searching for available updates. Please wait..." ),'', '', statuspng, divpng, None, '' )) + self["list"].style = "default" + self['list'].setList(self.statuslist) + elif status == 'sync': + statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgrade.png")) + self.statuslist.append(( _("Package list update"), '', _("Searching for new installed or removed packages. Please wait..." ),'', '', statuspng, divpng, None, '' )) + self["list"].style = "default" + self['list'].setList(self.statuslist) elif status == 'error': statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png")) - self.statuslist.append(( _("Error"), '', _("There was an error downloading the packetlist. Please try again." ),'',statuspng, divpng )) - self['list'].setList(self.statuslist) - - def rebuildList(self): - self.setStatus('update') - self.inv_cache = 0 - self.vc = valid_cache(self.cache_file, self.cache_ttl) - if self.cache_ttl > 0 and self.vc != 0: - try: - self.buildPacketList() - except: - self.inv_cache = 1 - if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0: - self.run = 0 - self.ipkg.startCmd(IpkgComponent.CMD_UPDATE) - - def go(self, returnValue = None): - cur = self["list"].getCurrent() - if cur: - status = cur[3] - package = cur[0] - self.cmdList = [] - if status == 'installed': - self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package })) - if len(self.cmdList): - self.session.openWithCallback(self.runRemove, MessageBox, _("Do you want to remove the package:\n") + package + "\n" + self.oktext) - elif status == 'upgradeable': - self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package })) - if len(self.cmdList): - self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to upgrade the package:\n") + package + "\n" + self.oktext) - elif status == "installable": - self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package })) - if len(self.cmdList): - self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to install the package:\n") + package + "\n" + self.oktext) + self.statuslist.append(( _("Error"), '', _("There was an error downloading the packetlist. Please try again." ),'', '', statuspng, divpng, None, '' )) + self["list"].style = "default" + self['list'].setList(self.statuslist) - def runRemove(self, result): - if result: - self.session.openWithCallback(self.runRemoveFinished, Ipkg, cmdList = self.cmdList) + def getUpdateInfos(self): + self.setState('update') + iSoftwareTools.getUpdates(self.getUpdateInfosCB) - def runRemoveFinished(self): - self.session.openWithCallback(self.RemoveReboot, MessageBox, _("Remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO) + def getUpdateInfosCB(self, retval = None): + if retval is not None: + if retval is True: + if iSoftwareTools.available_updates is not 0: + self["status"].setText(_("There are at least ") + str(iSoftwareTools.available_updates) + _(" updates available.")) + else: + self["status"].setText(_("There are no updates available.")) + elif retval is False: + self["status"].setText(_("No network connection available.")) + self.rebuildList() - def RemoveReboot(self, result): - if result is None: - return - if result is False: - cur = self["list"].getCurrent() - if cur: - item = self['list'].getIndex() - self.list[item] = self.buildEntryComponent(cur[0], cur[1], cur[2], 'installable') - self.cachelist[item] = [cur[0], cur[1], cur[2], 'installable'] - self['list'].setList(self.list) - write_cache(self.cache_file, self.cachelist) - self.reloadPluginlist() - if result: - quitMainloop(3) + def rebuildList(self, retval = None): + if self.currentSelectedTag is None: + self.buildCategoryList() + else: + self.buildPacketList(self.currentSelectedTag) - def runUpgrade(self, result): - if result: - self.session.openWithCallback(self.runUpgradeFinished, Ipkg, cmdList = self.cmdList) + def selectionChanged(self): + current = self["list"].getCurrent() + self["status"].setText("") + if current: + if self.currList == "packages": + self["key_red"].setText(_("Back")) + if current[4] == 'installed': + self["key_green"].setText(_("Uninstall")) + elif current[4] == 'installable': + self["key_green"].setText(_("Install")) + elif current[4] == 'remove': + self["key_green"].setText(_("Undo uninstall")) + elif current[4] == 'install': + self["key_green"].setText(_("Undo install")) + self["key_yellow"].setText(_("View details")) + self["key_blue"].setText("") + if len(self.selectedFiles) == 0 and iSoftwareTools.available_updates is not 0: + self["status"].setText(_("There are at least ") + str(iSoftwareTools.available_updates) + _(" updates available.")) + elif len(self.selectedFiles) is not 0: + self["status"].setText(str(len(self.selectedFiles)) + _(" packages selected.")) + else: + self["status"].setText(_("There are currently no outstanding actions.")) + elif self.currList == "category": + self["key_red"].setText(_("Close")) + self["key_green"].setText("") + self["key_yellow"].setText("") + self["key_blue"].setText("") + if len(self.selectedFiles) == 0 and iSoftwareTools.available_updates is not 0: + self["status"].setText(_("There are at least ") + str(iSoftwareTools.available_updates) + _(" updates available.")) + self["key_yellow"].setText(_("Update")) + elif len(self.selectedFiles) is not 0: + self["status"].setText(str(len(self.selectedFiles)) + _(" packages selected.")) + self["key_yellow"].setText(_("Process")) + else: + self["status"].setText(_("There are currently no outstanding actions.")) - def runUpgradeFinished(self): - self.session.openWithCallback(self.UpgradeReboot, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO) - - def UpgradeReboot(self, result): - if result is None: - return - if result is False: - cur = self["list"].getCurrent() - if cur: - item = self['list'].getIndex() - self.list[item] = self.buildEntryComponent(cur[0], cur[1], cur[2], 'installed') - self.cachelist[item] = [cur[0], cur[1], cur[2], 'installed'] - self['list'].setList(self.list) - write_cache(self.cache_file, self.cachelist) - self.reloadPluginlist() - if result: - quitMainloop(3) + def getSelectionState(self, detailsFile): + for entry in self.selectedFiles: + if entry[0] == detailsFile: + return True + return False - def ipkgCallback(self, event, param): - if event == IpkgComponent.EVENT_ERROR: - self.list_updating = False - self.setStatus('error') - elif event == IpkgComponent.EVENT_DONE: - if self.list_updating: - self.list_updating = False - if not self.Console: - self.Console = Console() - cmd = "ipkg list" - self.Console.ePopen(cmd, self.IpkgList_Finished) - #print event, "-", param - pass + def handleCurrent(self): + current = self["list"].getCurrent() + if current: + if self.currList == "category": + self.currentSelectedIndex = self["list"].index + selectedTag = current[2] + self.buildPacketList(selectedTag) + elif self.currList == "packages": + if current[7] is not '': + idx = self["list"].getIndex() + detailsFile = self.list[idx][1] + if self.list[idx][7] == True: + for entry in self.selectedFiles: + if entry[0] == detailsFile: + self.selectedFiles.remove(entry) + else: + alreadyinList = False + for entry in self.selectedFiles: + if entry[0] == detailsFile: + alreadyinList = True + if not alreadyinList: + self.selectedFiles.append((detailsFile,current[4],current[3])) + self.currentSelectedPackage = ((detailsFile,current[4],current[3])) + if current[4] == 'installed': + self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'remove', True) + elif current[4] == 'installable': + self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'install', True) + elif current[4] == 'remove': + self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'installed', False) + elif current[4] == 'install': + self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'installable',False) + self["list"].setList(self.list) + self["list"].setIndex(idx) + self["list"].updateList(self.list) + self.selectionChanged() - def IpkgList_Finished(self, result, retval, extra_args = None): - if len(result): - self.packetlist = [] - for x in result.splitlines(): - split = x.split(' - ') #self.blacklisted_packages - if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions): - self.packetlist.append([split[0].strip(), split[1].strip(),split[2].strip()]) - if not self.Console: - self.Console = Console() - cmd = "ipkg list_installed" - self.Console.ePopen(cmd, self.IpkgListInstalled_Finished) + def handleSelected(self): + current = self["list"].getCurrent() + if current: + if self.currList == "packages": + if current[7] is not '': + detailsfile = iSoftwareTools.directory[0] + "/" + current[1] + if (os_path.exists(detailsfile) == True): + self.saved_currentSelectedPackage = self.currentSelectedPackage + self.session.openWithCallback(self.detailsClosed, PluginDetails, self.skin_path, current) + else: + self.session.open(MessageBox, _("Sorry, no Details available!"), MessageBox.TYPE_INFO, timeout = 10) + elif self.currList == "category": + self.prepareInstall() + if len(self.cmdList): + self.session.openWithCallback(self.runExecute, PluginManagerInfo, self.skin_path, self.cmdList) - def IpkgListInstalled_Finished(self, result, retval, extra_args = None): - if len(result): - self.installed_packetlist = {} - for x in result.splitlines(): - split = x.split(' - ') - if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions): - self.installed_packetlist[split[0].strip()] = split[1].strip() - self.buildPacketList() + def detailsClosed(self, result = None): + if result is not None: + if result is not False: + self.setState('sync') + iSoftwareTools.lastDownloadDate = time() + for entry in self.selectedFiles: + if entry == self.saved_currentSelectedPackage: + self.selectedFiles.remove(entry) + iSoftwareTools.startIpkgListInstalled(self.rebuildList) - def buildEntryComponent(self, name, version, description, state): + def buildEntryComponent(self, name, details, description, packagename, state, selected = False): divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png")) + installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installed.png")) + installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installable.png")) + removepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png")) + installpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/install.png")) if state == 'installed': - installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installed.png")) - return((name, version, description, state, installedpng, divpng)) - elif state == 'upgradeable': - upgradeablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgradeable.png")) - return((name, version, description, state, upgradeablepng, divpng)) - else: - installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installable.png")) - return((name, version, description, state, installablepng, divpng)) + return((name, details, description, packagename, state, installedpng, divpng, selected)) + elif state == 'installable': + return((name, details, description, packagename, state, installablepng, divpng, selected)) + elif state == 'remove': + return((name, details, description, packagename, state, removepng, divpng, selected)) + elif state == 'install': + return((name, details, description, packagename, state, installpng, divpng, selected)) - def buildPacketList(self): - self.list = [] - self.cachelist = [] - - if self.cache_ttl > 0 and self.vc != 0: - print 'Loading packagelist cache from ',self.cache_file - try: - self.cachelist = load_cache(self.cache_file) - if len(self.cachelist) > 0: - for x in self.cachelist: - self.list.append(self.buildEntryComponent(x[0], x[1], x[2], x[3])) - self['list'].setList(self.list) - except: - self.inv_cache = 1 - - if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0: - print 'rebuilding fresh package list' + def buildPacketList(self, categorytag = None): + if categorytag is not None: + self.currList = "packages" + self.currentSelectedTag = categorytag + self.packetlist = [] + for package in iSoftwareTools.packagesIndexlist[:]: + prerequisites = package[0]["prerequisites"] + if prerequisites.has_key("tag"): + for foundtag in prerequisites["tag"]: + if categorytag == foundtag: + attributes = package[0]["attributes"] + if attributes.has_key("packagetype"): + if attributes["packagetype"] == "internal": + continue + self.packetlist.append([attributes["name"], attributes["details"], attributes["shortdescription"], attributes["packagename"]]) + else: + self.packetlist.append([attributes["name"], attributes["details"], attributes["shortdescription"], attributes["packagename"]]) + self.list = [] for x in self.packetlist: status = "" - if self.installed_packetlist.has_key(x[0].strip()): - if self.installed_packetlist[x[0].strip()] == x[1].strip(): - status = "installed" - self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status)) + name = x[0].strip() + details = x[1].strip() + description = x[2].strip() + packagename = x[3].strip() + selectState = self.getSelectionState(details) + if iSoftwareTools.installed_packetlist.has_key(packagename): + if selectState == True: + status = "remove" else: - status = "upgradeable" - self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status)) + status = "installed" + self.list.append(self.buildEntryComponent(name, details, description, packagename, status, selected = selectState)) else: - status = "installable" - self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status)) - if not any(x[0].strip().endswith(x) for x in self.unwanted_extensions): - self.cachelist.append([x[0].strip(), x[1].strip(), x[2].strip(), status]) - write_cache(self.cache_file, self.cachelist) + if selectState == True: + status = "install" + else: + status = "installable" + self.list.append(self.buildEntryComponent(name, details, description, packagename, status, selected = selectState)) + if len(self.list): + self.list.sort(key=lambda x: x[0]) + self["list"].style = "default" self['list'].setList(self.list) + self["list"].updateList(self.list) + self.selectionChanged() - def reloadPluginlist(self): - plugins.readPluginList(resolveFilename(SCOPE_PLUGINS)) + def buildCategoryList(self): + self.currList = "category" + self.categories = [] + self.categoryList = [] + for package in iSoftwareTools.packagesIndexlist[:]: + prerequisites = package[0]["prerequisites"] + if prerequisites.has_key("tag"): + for foundtag in prerequisites["tag"]: + attributes = package[0]["attributes"] + if foundtag not in self.categories: + self.categories.append(foundtag) + self.categoryList.append(self.buildCategoryComponent(foundtag)) + self.categoryList.sort(key=lambda x: x[0]) + self["list"].style = "category" + self['list'].setList(self.categoryList) + self["list"].updateList(self.categoryList) + self.selectionChanged() + def buildCategoryComponent(self, tag = None): + divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png")) + if tag is not None: + if tag == 'System': + return(( _("System"), _("View list of available system extensions" ), tag, divpng )) + elif tag == 'Skin': + return(( _("Skins"), _("View list of available skins" ), tag, divpng )) + elif tag == 'Recording': + return(( _("Recordings"), _("View list of available recording extensions" ), tag, divpng )) + elif tag == 'Network': + return(( _("Network"), _("View list of available networking extensions" ), tag, divpng )) + elif tag == 'CI': + return(( _("CommonInterface"), _("View list of available CommonInterface extensions" ), tag, divpng )) + elif tag == 'Default': + return(( _("Default Settings"), _("View list of available default settings" ), tag, divpng )) + elif tag == 'SAT': + return(( _("Satteliteequipment"), _("View list of available Satteliteequipment extensions." ), tag, divpng )) + elif tag == 'Software': + return(( _("Software"), _("View list of available software extensions" ), tag, divpng )) + elif tag == 'Multimedia': + return(( _("Multimedia"), _("View list of available multimedia extensions." ), tag, divpng )) + elif tag == 'Display': + return(( _("Display and Userinterface"), _("View list of available Display and Userinterface extensions." ), tag, divpng )) + elif tag == 'EPG': + return(( _("Electronic Program Guide"), _("View list of available EPG extensions." ), tag, divpng )) + elif tag == 'Communication': + return(( _("Communication"), _("View list of available communication extensions." ), tag, divpng )) + else: # dynamically generate non existent tags + return(( str(tag), _("View list of available ") + str(tag) + _(" extensions." ), tag, divpng )) -class PluginManager(Screen, DreamInfoHandler): + def prepareInstall(self): + self.cmdList = [] + if iSoftwareTools.available_updates > 0: + self.cmdList.append((IpkgComponent.CMD_UPGRADE, { "test_only": False })) + if self.selectedFiles and len(self.selectedFiles): + for plugin in self.selectedFiles: + detailsfile = iSoftwareTools.directory[0] + "/" + plugin[0] + if (os_path.exists(detailsfile) == True): + iSoftwareTools.fillPackageDetails(plugin[0]) + self.package = iSoftwareTools.packageDetails[0] + if self.package[0].has_key("attributes"): + self.attributes = self.package[0]["attributes"] + if self.attributes.has_key("package"): + self.packagefiles = self.attributes["package"] + if plugin[1] == 'installed': + if self.packagefiles: + for package in self.packagefiles[:]: + self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package["name"] })) + else: + self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": plugin[2] })) + else: + if self.packagefiles: + for package in self.packagefiles[:]: + self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package["name"] })) + else: + self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": plugin[2] })) + else: + if plugin[1] == 'installed': + self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": plugin[2] })) + else: + self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": plugin[2] })) + + def runExecute(self, result = None): + if result is not None: + if result[0] is True: + self.session.openWithCallback(self.runExecuteFinished, Ipkg, cmdList = self.cmdList) + elif result[0] is False: + self.cmdList = result[1] + self.session.openWithCallback(self.runExecuteFinished, Ipkg, cmdList = self.cmdList) + else: + self.close() + + def runExecuteFinished(self): + self.session.openWithCallback(self.ExecuteReboot, MessageBox, _("Install or remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO) + + def ExecuteReboot(self, result): + if result is None: + return + if result is False: + self.reloadPluginlist() + self.selectedFiles = [] + self.detailsClosed(True) + if result: + quitMainloop(3) - lastDownloadDate = None + def reloadPluginlist(self): + plugins.readPluginList(resolveFilename(SCOPE_PLUGINS)) + +class PluginManagerInfo(Screen): skin = """ - + - - - - - + - {"templates": - {"default": (51,[ - MultiContentEntryText(pos = (30, 1), size = (470, 24), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name - MultiContentEntryText(pos = (30, 25), size = (470, 20), font=1, flags = RT_HALIGN_LEFT, text = 2), # index 2 is the description - MultiContentEntryPixmapAlphaTest(pos = (475, 0), size = (48, 48), png = 5), # index 5 is the status pixmap - MultiContentEntryPixmapAlphaTest(pos = (0, 49), size = (550, 2), png = 6), # index 6 is the div pixmap - ]), - "category": (40,[ - MultiContentEntryText(pos = (30, 0), size = (500, 22), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name - MultiContentEntryText(pos = (30, 22), size = (500, 16), font=1, flags = RT_HALIGN_LEFT, text = 1), # index 1 is the description - MultiContentEntryPixmapAlphaTest(pos = (0, 38), size = (550, 2), png = 3), # index 3 is the div pixmap - ]) - }, - "fonts": [gFont("Regular", 22),gFont("Regular", 16)], - "itemHeight": 52 - } + {"template": [ + MultiContentEntryText(pos = (50, 0), size = (150, 26), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name + MultiContentEntryText(pos = (50, 27), size = (540, 23), font=1, flags = RT_HALIGN_LEFT, text = 1), # index 1 is the state + MultiContentEntryPixmapAlphaTest(pos = (0, 1), size = (48, 48), png = 2), # index 2 is the status pixmap + MultiContentEntryPixmapAlphaTest(pos = (0, 48), size = (550, 2), png = 3), # index 3 is the div pixmap + ], + "fonts": [gFont("Regular", 24),gFont("Regular", 22)], + "itemHeight": 50 + } - + + """ - def __init__(self, session, plugin_path, args = None): + def __init__(self, session, plugin_path, cmdlist = None): Screen.__init__(self, session) self.session = session self.skin_path = plugin_path - aboutInfo = about.getImageVersionString() - if aboutInfo.startswith("dev-"): - self.ImageVersion = 'Experimental' - else: - self.ImageVersion = 'Stable' - self.language = language.getLanguage()[:2] # getLanguage returns e.g. "fi_FI" for "language_country" - - DreamInfoHandler.__init__(self, self.statusCallback, blocking = False, neededTag = 'ALL_TAGS', neededFlag = self.ImageVersion, language = self.language) - self.directory = resolveFilename(SCOPE_METADIR) + self.cmdlist = cmdlist - self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions", "InfobarEPGActions", "HelpActions" ], + self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"], { - "ok": self.handleCurrent, + "ok": self.process_all, "back": self.exit, "red": self.exit, - "green": self.handleCurrent, - "yellow": self.handleSelected, - "showEventInfo": self.handleSelected, - "displayHelp": self.handleHelp, + "green": self.process_extensions, }, -1) self.list = [] - self.statuslist = [] - self.selectedFiles = [] - self.categoryList = [] self["list"] = List(self.list) - self["key_red"] = StaticText(_("Close")) - self["key_green"] = StaticText("") - self["key_yellow"] = StaticText("") - self["key_blue"] = StaticText("") - self["status"] = StaticText("") - - self.list_updating = True - self.packetlist = [] - self.installed_packetlist = {} - self.available_packetlist = [] - self.available_updates = 0 - self.Console = Console() - self.cmdList = [] - self.oktext = _("\nAfter pressing OK, please wait!") - self.unwanted_extensions = ('-dbg', '-dev', '-doc') - - self.ipkg = IpkgComponent() - self.ipkg.addCallback(self.ipkgCallback) - if not self.selectionChanged in self["list"].onSelectionChanged: - self["list"].onSelectionChanged.append(self.selectionChanged) - - self.currList = "" - self.currentSelectedTag = None - self.currentSelectedIndex = None + self["key_red"] = StaticText(_("Cancel")) + self["key_green"] = StaticText(_("Only extensions.")) + self["status"] = StaticText(_("Following tasks will be done after you press OK!")) self.onShown.append(self.setWindowTitle) self.onLayoutFinish.append(self.rebuildList) def setWindowTitle(self): - self.setTitle(_("Plugin manager")) - - def exit(self): - if self.currList == "packages": - self.currList = "category" - self.currentSelectedTag = None - self["list"].style = "category" - self['list'].setList(self.categoryList) - self["list"].setIndex(self.currentSelectedIndex) - self["list"].updateList(self.categoryList) - self.selectionChanged() - else: - self.ipkg.stop() - if self.Console is not None: - if len(self.Console.appContainers): - for name in self.Console.appContainers.keys(): - self.Console.kill(name) - self.prepareInstall() - if len(self.cmdList): - self.session.openWithCallback(self.runExecute, PluginManagerInfo, self.skin_path, self.cmdList) - else: - self.close() + self.setTitle(_("Plugin manager activity information")) - def handleHelp(self): - if self.currList != "status": - self.session.open(PluginManagerHelp, self.skin_path) + def rebuildList(self): + self.list = [] + if self.cmdlist is not None: + for entry in self.cmdlist: + action = "" + info = "" + cmd = entry[0] + if cmd == 0: + action = 'install' + elif cmd == 2: + action = 'remove' + else: + action = 'upgrade' + args = entry[1] + if cmd == 0: + info = args['package'] + elif cmd == 2: + info = args['package'] + else: + info = _("Dreambox software because updates are available.") - def setState(self,status = None): - if status: - self.currList = "status" - self.statuslist = [] - self["key_green"].setText("") - self["key_blue"].setText("") - self["key_yellow"].setText("") - divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png")) - if status == 'update': - statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgrade.png")) - self.statuslist.append(( _("Package list update"), '', _("Trying to download a new packetlist. Please wait..." ),'', '', statuspng, divpng, None, '' )) - self["list"].style = "default" - self['list'].setList(self.statuslist) - elif status == 'sync': - statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgrade.png")) - self.statuslist.append(( _("Package list update"), '', _("Searching for new installed or removed packages. Please wait..." ),'', '', statuspng, divpng, None, '' )) - self["list"].style = "default" - self['list'].setList(self.statuslist) - elif status == 'error': - statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png")) - self.statuslist.append(( _("Error"), '', _("There was an error downloading the packetlist. Please try again." ),'', '', statuspng, divpng, None, '' )) - self["list"].style = "default" - self['list'].setList(self.statuslist) - - def statusCallback(self, status, progress): - pass - - def selectionChanged(self): - current = self["list"].getCurrent() - self["status"].setText("") - if current: - if self.currList == "packages": - self["key_red"].setText(_("Back")) - if current[4] == 'installed': - self["key_green"].setText(_("Remove")) - elif current[4] == 'installable': - self["key_green"].setText(_("Install")) - elif current[4] == 'remove': - self["key_green"].setText(_("Undo\nRemove")) - elif current[4] == 'install': - self["key_green"].setText(_("Undo\nInstall")) - self["key_yellow"].setText(_("View details")) - self["key_blue"].setText("") - if len(self.selectedFiles) == 0 and self.available_updates is not 0: - self["status"].setText(_("There are at least ") + str(self.available_updates) + _(" updates available.")) - elif len(self.selectedFiles) is not 0: - self["status"].setText(str(len(self.selectedFiles)) + _(" packages selected.")) - else: - self["status"].setText(_("There is nothing to be done.")) - elif self.currList == "category": - self["key_red"].setText(_("Close")) - self["key_green"].setText("") - self["key_yellow"].setText("") - self["key_blue"].setText("") - if len(self.selectedFiles) == 0 and self.available_updates is not 0: - self["status"].setText(_("There are at least ") + str(self.available_updates) + _(" updates available.")) - self["key_yellow"].setText(_("Update")) - elif len(self.selectedFiles) is not 0: - self["status"].setText(str(len(self.selectedFiles)) + _(" packages selected.")) - self["key_yellow"].setText(_("Process")) - else: - self["status"].setText(_("There is nothing to be done.")) - - def getSelectionState(self, detailsFile): - for entry in self.selectedFiles: - if entry[0] == detailsFile: - return True - return False + self.list.append(self.buildEntryComponent(action,info)) + self['list'].setList(self.list) + self['list'].updateList(self.list) - def rebuildList(self): - self.setState('update') - if not PluginManager.lastDownloadDate or (time() - PluginManager.lastDownloadDate) > 3600: - # Only update from internet once per hour - PluginManager.lastDownloadDate = time() - print "last update time > 1h" - self.ipkg.startCmd(IpkgComponent.CMD_UPDATE) + def buildEntryComponent(self, action,info): + divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png")) + upgradepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgrade.png")) + installpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/install.png")) + removepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png")) + if action == 'install': + return(( _('Installing'), info, installpng, divpng)) + elif action == 'remove': + return(( _('Removing'), info, removepng, divpng)) else: - print "last update time < 1h" - self.startIpkgList() + return(( _('Upgrading'), info, upgradepng, divpng)) - def ipkgCallback(self, event, param): - if event == IpkgComponent.EVENT_ERROR: - self.list_updating = False - self.setState('error') - elif event == IpkgComponent.EVENT_DONE: - self.startIpkgList() - pass + def exit(self): + self.close() - def startIpkgList(self): - if self.list_updating: - if not self.Console: - self.Console = Console() - cmd = "ipkg list" - self.Console.ePopen(cmd, self.IpkgList_Finished) + def process_all(self): + self.close((True,None)) - def IpkgList_Finished(self, result, retval, extra_args = None): - if len(result): - self.available_packetlist = [] - for x in result.splitlines(): - split = x.split(' - ') - if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions): - self.available_packetlist.append([split[0].strip(), split[1].strip(), split[2].strip()]) - self.startInstallMetaPackage() + def process_extensions(self): + self.list = [] + if self.cmdlist is not None: + for entry in self.cmdlist: + cmd = entry[0] + if entry[0] in (0,2): + self.list.append((entry)) + self.close((False,self.list)) - def startInstallMetaPackage(self): - if self.list_updating: - self.list_updating = False - if not self.Console: - self.Console = Console() - cmd = "ipkg install enigma2-meta" #dummy,will change probably" - self.Console.ePopen(cmd, self.InstallMetaPackage_Finished) - def InstallMetaPackage_Finished(self, result, retval, extra_args = None): - if len(result): - self.fillPackagesIndexList() - if not self.Console: - self.Console = Console() - self.setState('sync') - cmd = "ipkg list_installed" - self.Console.ePopen(cmd, self.IpkgListInstalled_Finished) +class PluginManagerHelp(Screen): + skin = """ + + + + + + {"template": [ + MultiContentEntryText(pos = (50, 0), size = (150, 26), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name + MultiContentEntryText(pos = (50, 27), size = (540, 23), font=1, flags = RT_HALIGN_LEFT, text = 1), # index 1 is the state + MultiContentEntryPixmapAlphaTest(pos = (0, 1), size = (48, 48), png = 2), # index 2 is the status pixmap + MultiContentEntryPixmapAlphaTest(pos = (0, 48), size = (550, 2), png = 3), # index 3 is the div pixmap + ], + "fonts": [gFont("Regular", 24),gFont("Regular", 22)], + "itemHeight": 50 + } + + + + + """ - def IpkgListInstalled_Finished(self, result, retval, extra_args = None): - if len(result): - self.installed_packetlist = {} - for x in result.splitlines(): - split = x.split(' - ') - if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions): - self.installed_packetlist[split[0].strip()] = split[1].strip() - self.countUpdates() - if self.currentSelectedTag is None: - self.buildCategoryList() - else: - self.buildPacketList(self.currentSelectedTag) + def __init__(self, session, plugin_path): + Screen.__init__(self, session) + self.session = session + self.skin_path = plugin_path + + self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"], + { + "back": self.exit, + "red": self.exit, + }, -1) - def countUpdates(self): - self.available_updates = 0 - for package in self.packagesIndexlist[:]: - attributes = package[0]["attributes"] - packagename = attributes["packagename"] - for x in self.available_packetlist: - if x[0].strip() == packagename: - if self.installed_packetlist.has_key(packagename): - if self.installed_packetlist[packagename] != x[1].strip(): - self.available_updates +=1 + self.list = [] + self["list"] = List(self.list) + self["key_red"] = StaticText(_("Close")) + self["status"] = StaticText(_("A small overview of the available icon states and actions.")) - def handleCurrent(self): - current = self["list"].getCurrent() - if current: - if self.currList == "category": - self.currentSelectedIndex = self["list"].index - selectedTag = current[2] - self.buildPacketList(selectedTag) - elif self.currList == "packages": - if current[7] is not '': - idx = self["list"].getIndex() - detailsFile = self.list[idx][1] - if self.list[idx][7] == True: - for entry in self.selectedFiles: - if entry[0] == detailsFile: - self.selectedFiles.remove(entry) - else: - alreadyinList = False - for entry in self.selectedFiles: - if entry[0] == detailsFile: - alreadyinList = True - if not alreadyinList: - self.selectedFiles.append((detailsFile,current[4],current[3])) - if current[4] == 'installed': - self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'remove', True) - elif current[4] == 'installable': - self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'install', True) - elif current[4] == 'remove': - self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'installed', False) - elif current[4] == 'install': - self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'installable',False) - self["list"].setList(self.list) - self["list"].setIndex(idx) - self["list"].updateList(self.list) - self.selectionChanged() + self.onShown.append(self.setWindowTitle) + self.onLayoutFinish.append(self.rebuildList) - def handleSelected(self): - current = self["list"].getCurrent() - if current: - if self.currList == "packages": - if current[7] is not '': - detailsfile = self.directory[0] + "/" + current[1] - if (os_path.exists(detailsfile) == True): - self.session.openWithCallback(self.detailsClosed, PluginDetails, self.skin_path, current) - else: - self.session.open(MessageBox, _("Sorry, no Details available!"), MessageBox.TYPE_INFO, timeout = 10) - elif self.currList == "category": - self.prepareInstall() - if len(self.cmdList): - self.session.openWithCallback(self.runExecute, PluginManagerInfo, self.skin_path, self.cmdList) + def setWindowTitle(self): + self.setTitle(_("Plugin manager help")) - def detailsClosed(self, result): - if result: - if not self.Console: - self.Console = Console() - self.setState('sync') - PluginManager.lastDownloadDate = time() - self.selectedFiles = [] - cmd = "ipkg update" - self.Console.ePopen(cmd, self.InstallMetaPackage_Finished) + def rebuildList(self): + self.list = [] + self.list.append(self.buildEntryComponent('install')) + self.list.append(self.buildEntryComponent('installable')) + self.list.append(self.buildEntryComponent('installed')) + self.list.append(self.buildEntryComponent('remove')) + self['list'].setList(self.list) + self['list'].updateList(self.list) - def buildEntryComponent(self, name, details, description, packagename, state, selected = False): + def buildEntryComponent(self, state): divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png")) + installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installed.png")) + installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installable.png")) + removepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png")) + installpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/install.png")) + if state == 'installed': - installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installed.png")) - return((name, details, description, packagename, state, installedpng, divpng, selected)) + return(( _('This plugin is installed.'), _('You can remove this plugin.'), installedpng, divpng)) elif state == 'installable': - installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installable.png")) - return((name, details, description, packagename, state, installablepng, divpng, selected)) - elif state == 'remove': - removepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png")) - return((name, details, description, packagename, state, removepng, divpng, selected)) + return(( _('This plugin is not installed.'), _('You can install this plugin.'), installablepng, divpng)) elif state == 'install': - installpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/install.png")) - return((name, details, description, packagename, state, installpng, divpng, selected)) + return(( _('This plugin will be installed.'), _('You can cancel the installation.'), installpng, divpng)) + elif state == 'remove': + return(( _('This plugin will be removed.'), _('You can cancel the removal.'), removepng, divpng)) - def buildPacketList(self, categorytag = None): - if categorytag is not None: - self.currList = "packages" - self.currentSelectedTag = categorytag - self.packetlist = [] - for package in self.packagesIndexlist[:]: - prerequisites = package[0]["prerequisites"] - if prerequisites.has_key("tag"): - for foundtag in prerequisites["tag"]: - if categorytag == foundtag: - attributes = package[0]["attributes"] - if attributes.has_key("packagetype"): - if attributes["packagetype"] == "internal": - continue - self.packetlist.append([attributes["name"], attributes["details"], attributes["shortdescription"], attributes["packagename"]]) - else: - self.packetlist.append([attributes["name"], attributes["details"], attributes["shortdescription"], attributes["packagename"]]) - self.list = [] - for x in self.packetlist: - status = "" - selectState = self.getSelectionState(x[1].strip()) - if self.installed_packetlist.has_key(x[3].strip()): - if selectState == True: - status = "remove" - else: - status = "installed" - self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), x[3].strip(), status, selected = selectState)) - else: - if selectState == True: - status = "install" - else: - status = "installable" - self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), x[3].strip(), status, selected = selectState)) - if len(self.list): - self.list.sort(key=lambda x: x[0]) - self["list"].style = "default" - self['list'].setList(self.list) - self["list"].updateList(self.list) - self.selectionChanged() + def exit(self): + self.close() - def buildCategoryList(self): - self.currList = "category" - self.categories = [] - self.categoryList = [] - for package in self.packagesIndexlist[:]: - prerequisites = package[0]["prerequisites"] - if prerequisites.has_key("tag"): - for foundtag in prerequisites["tag"]: - attributes = package[0]["attributes"] - if foundtag not in self.categories: - self.categories.append(foundtag) - self.categoryList.append(self.buildCategoryComponent(foundtag)) - self.categoryList.sort(key=lambda x: x[0]) - self["list"].style = "category" - self['list'].setList(self.categoryList) - self["list"].updateList(self.categoryList) - self.selectionChanged() - def buildCategoryComponent(self, tag = None): - divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png")) - if tag is not None: - if tag == 'System': - return(( _("System"), _("View list of available system extensions" ), tag, divpng )) - elif tag == 'Skin': - return(( _("Skins"), _("View list of available skins" ), tag, divpng )) - elif tag == 'Recording': - return(( _("Recordings"), _("View list of available recording extensions" ), tag, divpng )) - elif tag == 'Network': - return(( _("Network"), _("View list of available networking extensions" ), tag, divpng )) - elif tag == 'CI': - return(( _("CommonInterface"), _("View list of available CommonInterface extensions" ), tag, divpng )) - elif tag == 'Default': - return(( _("Default Settings"), _("View list of available default settings" ), tag, divpng )) - elif tag == 'SAT': - return(( _("Satteliteequipment"), _("View list of available Satteliteequipment extensions." ), tag, divpng )) - elif tag == 'Software': - return(( _("Software"), _("View list of available software extensions" ), tag, divpng )) - elif tag == 'Multimedia': - return(( _("Multimedia"), _("View list of available multimedia extensions." ), tag, divpng )) - elif tag == 'Display': - return(( _("Display and Userinterface"), _("View list of available Display and Userinterface extensions." ), tag, divpng )) - elif tag == 'EPG': - return(( _("Electronic Program Guide"), _("View list of available EPG extensions." ), tag, divpng )) - elif tag == 'Communication': - return(( _("Communication"), _("View list of available communication extensions." ), tag, divpng )) - else: # dynamically generate non existent tags - return(( str(tag), _("View list of available ") + str(tag) + _(" extensions." ), tag, divpng )) +class PluginDetails(Screen, DreamInfoHandler): + skin = """ + + + + + + + + + + + """ + def __init__(self, session, plugin_path, packagedata = None): + Screen.__init__(self, session) + self.skin_path = plugin_path + self.language = language.getLanguage()[:2] # getLanguage returns e.g. "fi_FI" for "language_country" + self.attributes = None + self.translatedAttributes = None + DreamInfoHandler.__init__(self, self.statusCallback, blocking = False, language = self.language) + self.directory = resolveFilename(SCOPE_METADIR) + if packagedata: + self.pluginname = packagedata[0] + self.details = packagedata[1] + self.pluginstate = packagedata[4] + self.statuspicinstance = packagedata[5] + self.divpicinstance = packagedata[6] + self.fillPackageDetails(self.details) + + self.thumbnail = "" + + self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"], + { + "back": self.exit, + "red": self.exit, + "green": self.go, + "up": self.pageUp, + "down": self.pageDown, + "left": self.pageUp, + "right": self.pageDown, + }, -1) + + self["key_red"] = StaticText(_("Close")) + self["key_green"] = StaticText("") + self["author"] = StaticText() + self["statuspic"] = Pixmap() + self["divpic"] = Pixmap() + self["screenshot"] = Pixmap() + self["detailtext"] = ScrollLabel() + + self["statuspic"].hide() + self["screenshot"].hide() + self["divpic"].hide() + + self.package = self.packageDetails[0] + if self.package[0].has_key("attributes"): + self.attributes = self.package[0]["attributes"] + if self.package[0].has_key("translation"): + self.translatedAttributes = self.package[0]["translation"] - def prepareInstall(self): self.cmdList = [] - if self.available_updates > 0: - self.cmdList.append((IpkgComponent.CMD_UPGRADE, { "test_only": False })) - if self.selectedFiles and len(self.selectedFiles): - for plugin in self.selectedFiles: - detailsfile = self.directory[0] + "/" + plugin[0] - if (os_path.exists(detailsfile) == True): - self.fillPackageDetails(plugin[0]) - self.package = self.packageDetails[0] - if self.package[0].has_key("attributes"): - self.attributes = self.package[0]["attributes"] - if self.attributes.has_key("package"): - self.packagefiles = self.attributes["package"] - if plugin[1] == 'installed': - if self.packagefiles: - for package in self.packagefiles[:]: - self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package["name"] })) - else: - self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": plugin[2] })) - else: - if self.packagefiles: - for package in self.packagefiles[:]: - self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package["name"] })) - else: - self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": plugin[2] })) - else: - if plugin[1] == 'installed': - self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": plugin[2] })) - else: - self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": plugin[2] })) + self.oktext = _("\nAfter pressing OK, please wait!") + self.picload = ePicLoad() + self.picload.PictureData.get().append(self.paintScreenshotPixmapCB) + self.onShown.append(self.setWindowTitle) + self.onLayoutFinish.append(self.setInfos) + + def setWindowTitle(self): + self.setTitle(_("Details for extension: " + self.pluginname)) + + def exit(self): + self.close(False) + + def pageUp(self): + self["detailtext"].pageUp() + + def pageDown(self): + self["detailtext"].pageDown() + + def statusCallback(self, status, progress): + pass + + def setInfos(self): + if self.translatedAttributes.has_key("name"): + self.pluginname = self.translatedAttributes["name"] + elif self.attributes.has_key("name"): + self.pluginname = self.attributes["name"] + else: + self.pluginname = _("unknown") + + if self.translatedAttributes.has_key("author"): + self.author = self.translatedAttributes["author"] + elif self.attributes.has_key("author"): + self.author = self.attributes["author"] + else: + self.author = _("unknown") + + if self.translatedAttributes.has_key("description"): + self.description = self.translatedAttributes["description"] + elif self.attributes.has_key("description"): + self.description = self.attributes["description"] + else: + self.description = _("No description available.") + + if self.translatedAttributes.has_key("screenshot"): + self.loadThumbnail(self.translatedAttributes) + else: + self.loadThumbnail(self.attributes) + + self["author"].setText(_("Author: ") + self.author) + self["detailtext"].setText(self.description.strip()) + if self.pluginstate in ('installable', 'install'): + self["key_green"].setText(_("Install")) + else: + self["key_green"].setText(_("Remove")) + + def loadThumbnail(self, entry): + thumbnailUrl = None + if entry.has_key("screenshot"): + thumbnailUrl = entry["screenshot"] + if thumbnailUrl is not None: + self.thumbnail = "/tmp/" + thumbnailUrl.split('/')[-1] + print "[PluginDetails] downloading screenshot " + thumbnailUrl + " to " + self.thumbnail + client.downloadPage(thumbnailUrl,self.thumbnail).addCallback(self.setThumbnail).addErrback(self.fetchFailed) + else: + self.setThumbnail(noScreenshot = True) + + def setThumbnail(self, noScreenshot = False): + if not noScreenshot: + filename = self.thumbnail + else: + filename = resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/noprev.png") + + sc = AVSwitch().getFramebufferScale() + self.picload.setPara((self["screenshot"].instance.size().width(), self["screenshot"].instance.size().height(), sc[0], sc[1], False, 1, "#00000000")) + self.picload.startDecode(filename) + + if self.statuspicinstance != None: + self["statuspic"].instance.setPixmap(self.statuspicinstance.__deref__()) + self["statuspic"].show() + if self.divpicinstance != None: + self["divpic"].instance.setPixmap(self.divpicinstance.__deref__()) + self["divpic"].show() + + def paintScreenshotPixmapCB(self, picInfo=None): + ptr = self.picload.getData() + if ptr != None: + self["screenshot"].instance.setPixmap(ptr.__deref__()) + self["screenshot"].show() + else: + self.setThumbnail(noScreenshot = True) + + def go(self): + if self.attributes.has_key("package"): + self.packagefiles = self.attributes["package"] + self.cmdList = [] + if self.pluginstate in ('installed', 'remove'): + if self.packagefiles: + for package in self.packagefiles[:]: + self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package["name"] })) + if len(self.cmdList): + self.session.openWithCallback(self.runRemove, MessageBox, _("Do you want to remove the package:\n") + self.pluginname + "\n" + self.oktext) + else: + if self.packagefiles: + for package in self.packagefiles[:]: + self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package["name"] })) + if len(self.cmdList): + self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to install the package:\n") + self.pluginname + "\n" + self.oktext) + + def runUpgrade(self, result): + if result: + self.session.openWithCallback(self.runUpgradeFinished, Ipkg, cmdList = self.cmdList) + + def runUpgradeFinished(self): + self.session.openWithCallback(self.UpgradeReboot, MessageBox, _("Installation finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO) + + def UpgradeReboot(self, result): + if result is None: + return + if result is False: + self.close(True) + if result: + quitMainloop(3) + + def runRemove(self, result): + if result: + self.session.openWithCallback(self.runRemoveFinished, Ipkg, cmdList = self.cmdList) + + def runRemoveFinished(self): + self.session.openWithCallback(self.RemoveReboot, MessageBox, _("Remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO) + + def RemoveReboot(self, result): + if result is None: + return + if result is False: + self.close(True) + if result: + quitMainloop(3) + + def reloadPluginlist(self): + plugins.readPluginList(resolveFilename(SCOPE_PLUGINS)) + + def fetchFailed(self,string): + self.setThumbnail(noScreenshot = True) + print "[PluginDetails] fetch failed " + string.getErrorMessage() + + +class UpdatePlugin(Screen): + skin = """ + + + + + + """ + + def __init__(self, session, args = None): + Screen.__init__(self, session) + + self.sliderPackages = { "dreambox-dvb-modules": 1, "enigma2": 2, "tuxbox-image-info": 3 } + + self.slider = Slider(0, 4) + self["slider"] = self.slider + self.activityslider = Slider(0, 100) + self["activityslider"] = self.activityslider + self.status = StaticText(_("Upgrading Dreambox... Please wait")) + self["status"] = self.status + self.package = StaticText() + self["package"] = self.package + + self.packages = 0 + self.error = 0 + + self.activity = 0 + self.activityTimer = eTimer() + self.activityTimer.callback.append(self.doActivityTimer) + self.activityTimer.start(100, False) + + self.ipkg = IpkgComponent() + self.ipkg.addCallback(self.ipkgCallback) + + self.updating = True + self.package.setText(_("Package list update")) + self.ipkg.startCmd(IpkgComponent.CMD_UPDATE) + + self["actions"] = ActionMap(["WizardActions"], + { + "ok": self.exit, + "back": self.exit + }, -1) + + def doActivityTimer(self): + self.activity += 1 + if self.activity == 100: + self.activity = 0 + self.activityslider.setValue(self.activity) + + def ipkgCallback(self, event, param): + if event == IpkgComponent.EVENT_DOWNLOAD: + self.status.setText(_("Downloading")) + elif event == IpkgComponent.EVENT_UPGRADE: + if self.sliderPackages.has_key(param): + self.slider.setValue(self.sliderPackages[param]) + self.package.setText(param) + self.status.setText(_("Upgrading")) + self.packages += 1 + elif event == IpkgComponent.EVENT_INSTALL: + self.package.setText(param) + self.status.setText(_("Installing")) + self.packages += 1 + elif event == IpkgComponent.EVENT_CONFIGURING: + self.package.setText(param) + self.status.setText(_("Configuring")) + elif event == IpkgComponent.EVENT_MODIFIED: + self.session.openWithCallback( + self.modificationCallback, + MessageBox, + _("A configuration file (%s) was modified since Installation.\nDo you want to keep your version?") % (param) + ) + elif event == IpkgComponent.EVENT_ERROR: + self.error += 1 + elif event == IpkgComponent.EVENT_DONE: + if self.updating: + self.updating = False + self.ipkg.startCmd(IpkgComponent.CMD_UPGRADE, args = {'test_only': False}) + elif self.error == 0: + self.slider.setValue(4) + + self.activityTimer.stop() + self.activityslider.setValue(0) + + self.package.setText("") + self.status.setText(_("Done - Installed or upgraded %d packages") % self.packages) + else: + self.activityTimer.stop() + self.activityslider.setValue(0) + error = _("your dreambox might be unusable now. Please consult the manual for further assistance before rebooting your dreambox.") + if self.packages == 0: + error = _("No packages were upgraded yet. So you can check your network and try again.") + if self.updating: + error = _("Your dreambox isn't connected to the internet properly. Please check it and try again.") + self.status.setText(_("Error") + " - " + error) + #print event, "-", param + pass - def runExecute(self, result): - if result: - self.session.openWithCallback(self.runExecuteFinished, Ipkg, cmdList = self.cmdList) - else: - self.close() + def modificationCallback(self, res): + self.ipkg.write(res and "N" or "Y") - def runExecuteFinished(self): - self.session.openWithCallback(self.ExecuteReboot, MessageBox, _("Install or remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO) + def exit(self): + if not self.ipkg.isRunning(): + if self.packages != 0 and self.error == 0: + self.session.openWithCallback(self.exitAnswer, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?")) + else: + self.close() - def ExecuteReboot(self, result): - if result is None: - return - if result is False: - self.reloadPluginlist() - self.detailsClosed(True) - if result: - quitMainloop(3) + def exitAnswer(self, result): + if result is not None and result: + quitMainloop(2) + self.close() - def reloadPluginlist(self): - plugins.readPluginList(resolveFilename(SCOPE_PLUGINS)) -class PluginManagerInfo(Screen): +class IPKGMenu(Screen): skin = """ - + - - - {"template": [ - MultiContentEntryText(pos = (50, 1), size = (150, 24), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name - MultiContentEntryText(pos = (50, 25), size = (540, 24), font=1, flags = RT_HALIGN_LEFT, text = 1), # index 1 is the state - MultiContentEntryPixmapAlphaTest(pos = (0, 1), size = (48, 48), png = 2), # index 2 is the status pixmap - MultiContentEntryPixmapAlphaTest(pos = (0, 49), size = (550, 2), png = 3), # index 3 is the div pixmap - ], - "fonts": [gFont("Regular", 22),gFont("Regular", 18)], - "itemHeight": 52 - } - - - - + """ - def __init__(self, session, plugin_path, cmdlist = None): + def __init__(self, session, plugin_path): Screen.__init__(self, session) - self.session = session self.skin_path = plugin_path - self.cmdlist = cmdlist + + self["key_red"] = StaticText(_("Close")) + self["key_green"] = StaticText(_("Edit")) - self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"], + self.sel = [] + self.val = [] + self.entry = False + self.exe = False + + self.path = "" + + self["actions"] = NumberActionMap(["SetupActions"], { - "ok": self.process, - "back": self.exit, - "red": self.exit, - "green": self.process, + "ok": self.KeyOk, + "cancel": self.keyCancel }, -1) - self.list = [] - self["list"] = List(self.list) - self["key_red"] = StaticText(_("Cancel")) - self["key_green"] = StaticText(_("Continue")) - self["status"] = StaticText(_("Following tasks will be done after you press continue!")) + self["shortcuts"] = ActionMap(["ShortcutActions"], + { + "red": self.keyCancel, + "green": self.KeyOk, + }) + self.flist = [] + self["filelist"] = MenuList(self.flist) + self.fill_list() + self.onLayoutFinish.append(self.layoutFinished) - self.onShown.append(self.setWindowTitle) - self.onLayoutFinish.append(self.rebuildList) + def layoutFinished(self): + self.setWindowTitle() def setWindowTitle(self): - self.setTitle(_("Plugin manager activity information")) + self.setTitle(_("Select upgrade source to edit.")) - def rebuildList(self): - self.list = [] - if self.cmdlist is not None: - for entry in self.cmdlist: - action = "" - info = "" - cmd = entry[0] - if cmd == 0: - action = 'install' - elif cmd == 2: - action = 'remove' - else: - action = 'upgrade' - args = entry[1] - if cmd == 0: - info = args['package'] - elif cmd == 2: - info = args['package'] - else: - info = _("Dreambox software because updates are available.") + def fill_list(self): + self.flist = [] + self.path = '/etc/ipkg/' + if (os_path.exists(self.path) == False): + self.entry = False + return + for file in listdir(self.path): + if (file.endswith(".conf")): + if file != 'arch.conf': + self.flist.append((file)) + self.entry = True + self["filelist"].l.setList(self.flist) - self.list.append(self.buildEntryComponent(action,info)) - self['list'].setList(self.list) - self['list'].updateList(self.list) + def KeyOk(self): + if (self.exe == False) and (self.entry == True): + self.sel = self["filelist"].getCurrent() + self.val = self.path + self.sel + self.session.open(IPKGSource, self.val) - def buildEntryComponent(self, action,info): - divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png")) - upgradepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgrade.png")) - installpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/install.png")) - removepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png")) - if action == 'install': - return(( _('Installing'), info, installpng, divpng)) - elif action == 'remove': - return(( _('Removing'), info, removepng, divpng)) + def keyCancel(self): + self.close() + + def Exit(self): + self.close() + + +class IPKGSource(Screen): + skin = """ + + + + + + + """ + + def __init__(self, session, configfile = None): + Screen.__init__(self, session) + self.session = session + self.configfile = configfile + text = "" + if self.configfile: + try: + fp = file(configfile, 'r') + sources = fp.readlines() + if sources: + text = sources[0] + fp.close() + except IOError: + pass + + desk = getDesktop(0) + x= int(desk.size().width()) + y= int(desk.size().height()) + + self["key_red"] = StaticText(_("Cancel")) + self["key_green"] = StaticText(_("Save")) + + if (y>=720): + self["text"] = Input(text, maxSize=False, type=Input.TEXT) else: - return(( _('Upgrading'), info, upgradepng, divpng)) + self["text"] = Input(text, maxSize=False, visible_width = 55, type=Input.TEXT) - def exit(self): - self.close(False) + self["actions"] = NumberActionMap(["WizardActions", "InputActions", "TextEntryActions", "KeyboardInputActions","ShortcutActions"], + { + "ok": self.go, + "back": self.close, + "red": self.close, + "green": self.go, + "left": self.keyLeft, + "right": self.keyRight, + "home": self.keyHome, + "end": self.keyEnd, + "deleteForward": self.keyDeleteForward, + "deleteBackward": self.keyDeleteBackward, + "1": self.keyNumberGlobal, + "2": self.keyNumberGlobal, + "3": self.keyNumberGlobal, + "4": self.keyNumberGlobal, + "5": self.keyNumberGlobal, + "6": self.keyNumberGlobal, + "7": self.keyNumberGlobal, + "8": self.keyNumberGlobal, + "9": self.keyNumberGlobal, + "0": self.keyNumberGlobal + }, -1) - def process(self): - self.close(True) + self.onLayoutFinish.append(self.layoutFinished) + + def layoutFinished(self): + self.setWindowTitle() + self["text"].right() + def setWindowTitle(self): + self.setTitle(_("Edit upgrade source url.")) -class PluginManagerHelp(Screen): + def go(self): + text = self["text"].getText() + if text: + fp = file(self.configfile, 'w') + fp.write(text) + fp.write("\n") + fp.close() + self.close() + + def keyLeft(self): + self["text"].left() + + def keyRight(self): + self["text"].right() + + def keyHome(self): + self["text"].home() + + def keyEnd(self): + self["text"].end() + + def keyDeleteForward(self): + self["text"].delete() + + def keyDeleteBackward(self): + self["text"].deleteBackward() + + def keyNumberGlobal(self, number): + self["text"].number(number) + + +class PacketManager(Screen): skin = """ - + + - + + {"template": [ - MultiContentEntryText(pos = (50, 1), size = (540, 24), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name - MultiContentEntryText(pos = (50, 25), size = (540, 24), font=1, flags = RT_HALIGN_LEFT, text = 1), # index 1 is the state - MultiContentEntryPixmapAlphaTest(pos = (0, 1), size = (48, 48), png = 2), # index 2 is the status pixmap - MultiContentEntryPixmapAlphaTest(pos = (0, 49), size = (550, 2), png = 3), # index 3 is the div pixmap + MultiContentEntryText(pos = (5, 1), size = (440, 28), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name + MultiContentEntryText(pos = (5, 26), size = (440, 20), font=1, flags = RT_HALIGN_LEFT, text = 2), # index 2 is the description + MultiContentEntryPixmapAlphaTest(pos = (445, 2), size = (48, 48), png = 4), # index 4 is the status pixmap + MultiContentEntryPixmapAlphaTest(pos = (5, 50), size = (510, 2), png = 5), # index 4 is the div pixmap ], - "fonts": [gFont("Regular", 22),gFont("Regular", 18)], + "fonts": [gFont("Regular", 22),gFont("Regular", 14)], "itemHeight": 52 } - - """ - - def __init__(self, session, plugin_path): + + def __init__(self, session, plugin_path, args = None): Screen.__init__(self, session) self.session = session self.skin_path = plugin_path - self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"], + self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"], { + "ok": self.go, "back": self.exit, "red": self.exit, + "green": self.reload, }, -1) - + self.list = [] + self.statuslist = [] self["list"] = List(self.list) self["key_red"] = StaticText(_("Close")) - self["status"] = StaticText(_("A small overview of the available icon states and actions.")) + self["key_green"] = StaticText(_("Reload")) + + self.list_updating = True + self.packetlist = [] + self.installed_packetlist = {} + self.Console = Console() + self.cmdList = [] + self.cachelist = [] + self.cache_ttl = 86400 #600 is default, 0 disables, Seconds cache is considered valid (24h should be ok for caching ipkgs) + self.cache_file = '/usr/lib/enigma2/python/Plugins/SystemPlugins/SoftwareManager/packetmanager.cache' #Path to cache directory + self.oktext = _("\nAfter pressing OK, please wait!") + self.unwanted_extensions = ('-dbg', '-dev', '-doc', 'busybox') + self.ipkg = IpkgComponent() + self.ipkg.addCallback(self.ipkgCallback) self.onShown.append(self.setWindowTitle) self.onLayoutFinish.append(self.rebuildList) - def setWindowTitle(self): - self.setTitle(_("Plugin manager help")) - - def rebuildList(self): - self.list = [] - self.list.append(self.buildEntryComponent('install')) - self.list.append(self.buildEntryComponent('installable')) - self.list.append(self.buildEntryComponent('installed')) - self.list.append(self.buildEntryComponent('remove')) - self['list'].setList(self.list) - self['list'].updateList(self.list) - - def buildEntryComponent(self, state): - divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png")) - installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installed.png")) - installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installable.png")) - removepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png")) - installpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/install.png")) - - if state == 'installed': - return(( _('This plugin is installed.'), _('You can remove this plugin.'), installedpng, divpng)) - elif state == 'installable': - return(( _('This plugin is not installed.'), _('You can install this plugin.'), installablepng, divpng)) - elif state == 'install': - return(( _('This plugin will be installed.'), _('You can cancel the installation.'), installpng, divpng)) - elif state == 'remove': - return(( _('This plugin will be removed.'), _('You can cancel the removal.'), removepng, divpng)) - def exit(self): + self.ipkg.stop() + if self.Console is not None: + if len(self.Console.appContainers): + for name in self.Console.appContainers.keys(): + self.Console.kill(name) self.close() - -class PluginDetails(Screen, DreamInfoHandler): - skin = """ - - - - - - - - - - - """ - def __init__(self, session, plugin_path, packagedata = None): - Screen.__init__(self, session) - self.skin_path = plugin_path - self.language = language.getLanguage()[:2] # getLanguage returns e.g. "fi_FI" for "language_country" - self.attributes = None - self.translatedAttributes = None - DreamInfoHandler.__init__(self, self.statusCallback, blocking = False, language = self.language) - self.directory = resolveFilename(SCOPE_METADIR) - if packagedata: - self.pluginname = packagedata[0] - self.details = packagedata[1] - self.pluginstate = packagedata[4] - self.statuspicinstance = packagedata[5] - self.divpicinstance = packagedata[6] - self.fillPackageDetails(self.details) - - self.thumbnail = "" - - self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"], - { - "back": self.exit, - "red": self.exit, - "green": self.go, - "up": self.pageUp, - "down": self.pageDown, - "left": self.pageUp, - "right": self.pageDown, - }, -1) - - self["key_red"] = StaticText(_("Close")) - self["key_green"] = StaticText("") - self["author"] = StaticText() - self["statuspic"] = Pixmap() - self["divpic"] = Pixmap() - self["screenshot"] = Pixmap() - self["detailtext"] = ScrollLabel() - - self["statuspic"].hide() - self["screenshot"].hide() - self["divpic"].hide() - - self.package = self.packageDetails[0] - if self.package[0].has_key("attributes"): - self.attributes = self.package[0]["attributes"] - if self.package[0].has_key("translation"): - self.translatedAttributes = self.package[0]["translation"] - - self.cmdList = [] - self.oktext = _("\nAfter pressing OK, please wait!") - self.picload = ePicLoad() - self.picload.PictureData.get().append(self.paintScreenshotPixmapCB) - self.onShown.append(self.setWindowTitle) - self.onLayoutFinish.append(self.setInfos) - + def reload(self): + if (os_path.exists(self.cache_file) == True): + remove(self.cache_file) + self.list_updating = True + self.rebuildList() + def setWindowTitle(self): - self.setTitle(_("Package details for: " + self.pluginname)) - - def exit(self): - self.close(False) - - def pageUp(self): - self["detailtext"].pageUp() - - def pageDown(self): - self["detailtext"].pageDown() - - def statusCallback(self, status, progress): - pass - - def setInfos(self): - if self.translatedAttributes.has_key("name"): - self.pluginname = self.translatedAttributes["name"] - elif self.attributes.has_key("name"): - self.pluginname = self.attributes["name"] - else: - self.pluginname = _("unknown") - - if self.translatedAttributes.has_key("author"): - self.author = self.translatedAttributes["author"] - elif self.attributes.has_key("author"): - self.author = self.attributes["author"] - else: - self.author = _("unknown") - - if self.translatedAttributes.has_key("description"): - self.description = self.translatedAttributes["description"] - elif self.attributes.has_key("description"): - self.description = self.attributes["description"] - else: - self.description = _("No description available.") - - if self.translatedAttributes.has_key("screenshot"): - self.loadThumbnail(self.translatedAttributes) - else: - self.loadThumbnail(self.attributes) - - self["author"].setText(_("Author: ") + self.author) - self["detailtext"].setText(self.description.strip()) - if self.pluginstate == 'installable': - self["key_green"].setText(_("Install")) - else: - self["key_green"].setText(_("Remove")) - - def loadThumbnail(self, entry): - thumbnailUrl = None - if entry.has_key("screenshot"): - thumbnailUrl = entry["screenshot"] - if thumbnailUrl is not None: - self.thumbnail = "/tmp/" + thumbnailUrl.split('/')[-1] - print "[PluginDetails] downloading screenshot " + thumbnailUrl + " to " + self.thumbnail - client.downloadPage(thumbnailUrl,self.thumbnail).addCallback(self.setThumbnail).addErrback(self.fetchFailed) - else: - self.setThumbnail(noScreenshot = True) - - def setThumbnail(self, noScreenshot = False): - if not noScreenshot: - filename = self.thumbnail - else: - filename = resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/noprev.png") - - sc = AVSwitch().getFramebufferScale() - self.picload.setPara((self["screenshot"].instance.size().width(), self["screenshot"].instance.size().height(), sc[0], sc[1], False, 1, "#00000000")) - self.picload.startDecode(filename) - - if self.statuspicinstance != None: - self["statuspic"].instance.setPixmap(self.statuspicinstance.__deref__()) - self["statuspic"].show() - if self.divpicinstance != None: - self["divpic"].instance.setPixmap(self.divpicinstance.__deref__()) - self["divpic"].show() - - def paintScreenshotPixmapCB(self, picInfo=None): - ptr = self.picload.getData() - if ptr != None: - self["screenshot"].instance.setPixmap(ptr.__deref__()) - self["screenshot"].show() - else: - self.setThumbnail(noScreenshot = True) - - def go(self): - if self.attributes.has_key("package"): - self.packagefiles = self.attributes["package"] - self.cmdList = [] - if self.pluginstate == 'installed': - if self.packagefiles: - for package in self.packagefiles[:]: - self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package["name"] })) - if len(self.cmdList): - self.session.openWithCallback(self.runRemove, MessageBox, _("Do you want to remove the package:\n") + self.pluginname + "\n" + self.oktext) - else: - if self.packagefiles: - for package in self.packagefiles[:]: - self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package["name"] })) - if len(self.cmdList): - self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to install the package:\n") + self.pluginname + "\n" + self.oktext) + self.setTitle(_("Packet manager")) - def runUpgrade(self, result): - if result: - self.session.openWithCallback(self.runUpgradeFinished, Ipkg, cmdList = self.cmdList) + def setStatus(self,status = None): + if status: + self.statuslist = [] + divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png")) + if status == 'update': + statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgrade.png")) + self.statuslist.append(( _("Package list update"), '', _("Trying to download a new packetlist. Please wait..." ),'',statuspng, divpng )) + self['list'].setList(self.statuslist) + elif status == 'error': + statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png")) + self.statuslist.append(( _("Error"), '', _("There was an error downloading the packetlist. Please try again." ),'',statuspng, divpng )) + self['list'].setList(self.statuslist) - def runUpgradeFinished(self): - self.session.openWithCallback(self.UpgradeReboot, MessageBox, _("Installation finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO) + def rebuildList(self): + self.setStatus('update') + self.inv_cache = 0 + self.vc = valid_cache(self.cache_file, self.cache_ttl) + if self.cache_ttl > 0 and self.vc != 0: + try: + self.buildPacketList() + except: + self.inv_cache = 1 + if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0: + self.run = 0 + self.ipkg.startCmd(IpkgComponent.CMD_UPDATE) - def UpgradeReboot(self, result): - if result is None: - return - if result is False: - self.close(True) - if result: - quitMainloop(3) + def go(self, returnValue = None): + cur = self["list"].getCurrent() + if cur: + status = cur[3] + package = cur[0] + self.cmdList = [] + if status == 'installed': + self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package })) + if len(self.cmdList): + self.session.openWithCallback(self.runRemove, MessageBox, _("Do you want to remove the package:\n") + package + "\n" + self.oktext) + elif status == 'upgradeable': + self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package })) + if len(self.cmdList): + self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to upgrade the package:\n") + package + "\n" + self.oktext) + elif status == "installable": + self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package })) + if len(self.cmdList): + self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to install the package:\n") + package + "\n" + self.oktext) def runRemove(self, result): if result: @@ -1528,131 +1508,122 @@ class PluginDetails(Screen, DreamInfoHandler): if result is None: return if result is False: - self.close(True) + cur = self["list"].getCurrent() + if cur: + item = self['list'].getIndex() + self.list[item] = self.buildEntryComponent(cur[0], cur[1], cur[2], 'installable') + self.cachelist[item] = [cur[0], cur[1], cur[2], 'installable'] + self['list'].setList(self.list) + write_cache(self.cache_file, self.cachelist) + self.reloadPluginlist() if result: quitMainloop(3) - def reloadPluginlist(self): - plugins.readPluginList(resolveFilename(SCOPE_PLUGINS)) - - def fetchFailed(self,string): - self.setThumbnail(noScreenshot = True) - print "[PluginDetails] fetch failed " + string.getErrorMessage() - - -class UpdatePlugin(Screen): - skin = """ - - - - - - """ - - def __init__(self, session, args = None): - Screen.__init__(self, session) - - self.sliderPackages = { "dreambox-dvb-modules": 1, "enigma2": 2, "tuxbox-image-info": 3 } - - self.slider = Slider(0, 4) - self["slider"] = self.slider - self.activityslider = Slider(0, 100) - self["activityslider"] = self.activityslider - self.status = StaticText(_("Upgrading Dreambox... Please wait")) - self["status"] = self.status - self.package = StaticText() - self["package"] = self.package - - self.packages = 0 - self.error = 0 - - self.activity = 0 - self.activityTimer = eTimer() - self.activityTimer.callback.append(self.doActivityTimer) - self.activityTimer.start(100, False) - - self.ipkg = IpkgComponent() - self.ipkg.addCallback(self.ipkgCallback) - - self.updating = True - self.package.setText(_("Package list update")) - self.ipkg.startCmd(IpkgComponent.CMD_UPDATE) - - self["actions"] = ActionMap(["WizardActions"], - { - "ok": self.exit, - "back": self.exit - }, -1) + def runUpgrade(self, result): + if result: + self.session.openWithCallback(self.runUpgradeFinished, Ipkg, cmdList = self.cmdList) - def doActivityTimer(self): - self.activity += 1 - if self.activity == 100: - self.activity = 0 - self.activityslider.setValue(self.activity) + def runUpgradeFinished(self): + self.session.openWithCallback(self.UpgradeReboot, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO) + + def UpgradeReboot(self, result): + if result is None: + return + if result is False: + cur = self["list"].getCurrent() + if cur: + item = self['list'].getIndex() + self.list[item] = self.buildEntryComponent(cur[0], cur[1], cur[2], 'installed') + self.cachelist[item] = [cur[0], cur[1], cur[2], 'installed'] + self['list'].setList(self.list) + write_cache(self.cache_file, self.cachelist) + self.reloadPluginlist() + if result: + quitMainloop(3) def ipkgCallback(self, event, param): - if event == IpkgComponent.EVENT_DOWNLOAD: - self.status.setText(_("Downloading")) - elif event == IpkgComponent.EVENT_UPGRADE: - if self.sliderPackages.has_key(param): - self.slider.setValue(self.sliderPackages[param]) - self.package.setText(param) - self.status.setText(_("Upgrading")) - self.packages += 1 - elif event == IpkgComponent.EVENT_INSTALL: - self.package.setText(param) - self.status.setText(_("Installing")) - self.packages += 1 - elif event == IpkgComponent.EVENT_CONFIGURING: - self.package.setText(param) - self.status.setText(_("Configuring")) - elif event == IpkgComponent.EVENT_MODIFIED: - self.session.openWithCallback( - self.modificationCallback, - MessageBox, - _("A configuration file (%s) was modified since Installation.\nDo you want to keep your version?") % (param) - ) - elif event == IpkgComponent.EVENT_ERROR: - self.error += 1 + if event == IpkgComponent.EVENT_ERROR: + self.list_updating = False + self.setStatus('error') elif event == IpkgComponent.EVENT_DONE: - if self.updating: - self.updating = False - self.ipkg.startCmd(IpkgComponent.CMD_UPGRADE, args = {'test_only': False}) - elif self.error == 0: - self.slider.setValue(4) - - self.activityTimer.stop() - self.activityslider.setValue(0) - - self.package.setText("") - self.status.setText(_("Done - Installed or upgraded %d packages") % self.packages) - else: - self.activityTimer.stop() - self.activityslider.setValue(0) - error = _("your dreambox might be unusable now. Please consult the manual for further assistance before rebooting your dreambox.") - if self.packages == 0: - error = _("No packages were upgraded yet. So you can check your network and try again.") - if self.updating: - error = _("Your dreambox isn't connected to the internet properly. Please check it and try again.") - self.status.setText(_("Error") + " - " + error) + if self.list_updating: + self.list_updating = False + if not self.Console: + self.Console = Console() + cmd = "ipkg list" + self.Console.ePopen(cmd, self.IpkgList_Finished) #print event, "-", param pass - def modificationCallback(self, res): - self.ipkg.write(res and "N" or "Y") + def IpkgList_Finished(self, result, retval, extra_args = None): + if len(result): + self.packetlist = [] + for x in result.splitlines(): + split = x.split(' - ') #self.blacklisted_packages + if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions): + self.packetlist.append([split[0].strip(), split[1].strip(),split[2].strip()]) + if not self.Console: + self.Console = Console() + cmd = "ipkg list_installed" + self.Console.ePopen(cmd, self.IpkgListInstalled_Finished) - def exit(self): - if not self.ipkg.isRunning(): - if self.packages != 0 and self.error == 0: - self.session.openWithCallback(self.exitAnswer, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?")) - else: - self.close() + def IpkgListInstalled_Finished(self, result, retval, extra_args = None): + if len(result): + self.installed_packetlist = {} + for x in result.splitlines(): + split = x.split(' - ') + if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions): + self.installed_packetlist[split[0].strip()] = split[1].strip() + self.buildPacketList() - def exitAnswer(self, result): - if result is not None and result: - quitMainloop(2) - self.close() + def buildEntryComponent(self, name, version, description, state): + divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png")) + if state == 'installed': + installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installed.png")) + return((name, version, description, state, installedpng, divpng)) + elif state == 'upgradeable': + upgradeablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgradeable.png")) + return((name, version, description, state, upgradeablepng, divpng)) + else: + installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installable.png")) + return((name, version, description, state, installablepng, divpng)) + + def buildPacketList(self): + self.list = [] + self.cachelist = [] + + if self.cache_ttl > 0 and self.vc != 0: + print 'Loading packagelist cache from ',self.cache_file + try: + self.cachelist = load_cache(self.cache_file) + if len(self.cachelist) > 0: + for x in self.cachelist: + self.list.append(self.buildEntryComponent(x[0], x[1], x[2], x[3])) + self['list'].setList(self.list) + except: + self.inv_cache = 1 + + if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0: + print 'rebuilding fresh package list' + for x in self.packetlist: + status = "" + if self.installed_packetlist.has_key(x[0].strip()): + if self.installed_packetlist[x[0].strip()] == x[1].strip(): + status = "installed" + self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status)) + else: + status = "upgradeable" + self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status)) + else: + status = "installable" + self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status)) + if not any(x[0].strip().endswith(x) for x in self.unwanted_extensions): + self.cachelist.append([x[0].strip(), x[1].strip(), x[2].strip(), status]) + write_cache(self.cache_file, self.cachelist) + self['list'].setList(self.list) + def reloadPluginlist(self): + plugins.readPluginList(resolveFilename(SCOPE_PLUGINS)) class IpkgInstaller(Screen): skin = """ @@ -1719,15 +1690,20 @@ def UpgradeMain(session, **kwargs): def startSetup(menuid): if menuid != "setup": return [ ] - return [(_("Software manager"), UpgradeMain, "software_manager", 50)] + return [(_("Software management"), UpgradeMain, "software_manager", 50)] + +def autostart(reason, **kwargs): + if reason is True: + iSoftwareTools.startSoftwareTools() def Plugins(path, **kwargs): global plugin_path plugin_path = path list = [ - PluginDescriptor(name=_("Software manager"), description=_("Manage your receiver's software"), where = PluginDescriptor.WHERE_MENU, fnc=startSetup), + PluginDescriptor(where = [PluginDescriptor.WHERE_NETWORKCONFIG_READ], fnc = autostart), + PluginDescriptor(name=_("Software management"), description=_("Manage your receiver's software"), where = PluginDescriptor.WHERE_MENU, fnc=startSetup), PluginDescriptor(name=_("Ipkg"), where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan) ] if config.usage.setup_level.index >= 2: # expert+ - list.append(PluginDescriptor(name=_("Software manager"), description=_("Manage your receiver's software"), where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc=UpgradeMain)) + list.append(PluginDescriptor(name=_("Software management"), description=_("Manage your receiver's software"), where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc=UpgradeMain)) return list diff --git a/lib/python/Screens/ChannelSelection.py b/lib/python/Screens/ChannelSelection.py index 36a54e77..5fbfd591 100644 --- a/lib/python/Screens/ChannelSelection.py +++ b/lib/python/Screens/ChannelSelection.py @@ -22,6 +22,7 @@ from Components.Input import Input profile("ChannelSelection.py 3") from Components.ParentalControl import parentalControl from Components.ChoiceList import ChoiceList, ChoiceEntryComponent +from Components.SystemInfo import SystemInfo from Screens.InputBox import InputBox, PinInput from Screens.MessageBox import MessageBox from Screens.ServiceInfo import ServiceInfo @@ -126,7 +127,7 @@ class ChannelContextMenu(Screen): append_when_current_valid(current, menu, (_("remove entry"), self.removeCurrentService), level = 0) if current_root and current_root.getPath().find("flags == %d" %(FLAG_SERVICE_NEW_FOUND)) != -1: append_when_current_valid(current, menu, (_("remove new found flag"), self.removeNewFoundFlag), level = 0) - if isPlayable: + if isPlayable and SystemInfo.get("NumVideoDecoders", 1) > 1: append_when_current_valid(current, menu, (_("Activate Picture in Picture"), self.showServiceInPiP), level = 0, key = "blue") self.pipAvailable = True else: diff --git a/lib/python/Screens/InfoBarGenerics.py b/lib/python/Screens/InfoBarGenerics.py index 6dd80533..7ae0b123 100644 --- a/lib/python/Screens/InfoBarGenerics.py +++ b/lib/python/Screens/InfoBarGenerics.py @@ -725,6 +725,7 @@ class InfoBarSeek: iPlayableService.evEOF: self.__evEOF, iPlayableService.evSOF: self.__evSOF, }) + self.fast_winding_hint_message_showed = False class InfoBarSeekActionMap(HelpableActionMap): def __init__(self, screen, *args, **kwargs): @@ -851,6 +852,7 @@ class InfoBarSeek: # print "seekable" def __serviceStarted(self): + self.fast_winding_hint_message_showed = False self.seekstate = self.SEEK_STATE_PLAY self.__seekableStatusChanged() @@ -941,6 +943,13 @@ class InfoBarSeek: self.showAfterSeek() def seekFwd(self): + seek = self.getSeek() + if seek and not (seek.isCurrentlySeekable() & 2): + if not self.fast_winding_hint_message_showed and (seek.isCurrentlySeekable() & 1): + self.session.open(MessageBox, _("No fast winding possible yet.. but you can use the number buttons to skip forward/backward!"), MessageBox.TYPE_INFO, timeout=10) + self.fast_winding_hint_message_showed = True + return + return 0 # trade as unhandled action if self.seekstate == self.SEEK_STATE_PLAY: self.setSeekState(self.makeStateForward(int(config.seek.enter_forward.value))) elif self.seekstate == self.SEEK_STATE_PAUSE: @@ -970,6 +979,13 @@ class InfoBarSeek: self.setSeekState(self.makeStateSlowMotion(speed)) def seekBack(self): + seek = self.getSeek() + if seek and not (seek.isCurrentlySeekable() & 2): + if not self.fast_winding_hint_message_showed and (seek.isCurrentlySeekable() & 1): + self.session.open(MessageBox, _("No fast winding possible yet.. but you can use the number buttons to skip forward/backward!"), MessageBox.TYPE_INFO, timeout=10) + self.fast_winding_hint_message_showed = True + return + return 0 # trade as unhandled action seekstate = self.seekstate if seekstate == self.SEEK_STATE_PLAY: self.setSeekState(self.makeStateBackward(int(config.seek.enter_backward.value))) diff --git a/lib/python/Screens/PluginBrowser.py b/lib/python/Screens/PluginBrowser.py index 61bb7d0a..cce08aed 100755 --- a/lib/python/Screens/PluginBrowser.py +++ b/lib/python/Screens/PluginBrowser.py @@ -9,7 +9,7 @@ from Components.Label import Label from Screens.MessageBox import MessageBox from Screens.Console import Console from Plugins.Plugin import PluginDescriptor -from Tools.Directories import resolveFilename, SCOPE_PLUGINS, SCOPE_SKIN_IMAGE +from Tools.Directories import resolveFilename, fileExists, SCOPE_PLUGINS, SCOPE_SKIN_IMAGE from Tools.LoadPixmap import LoadPixmap from time import time @@ -22,19 +22,23 @@ class PluginBrowser(Screen): def __init__(self, session): Screen.__init__(self, session) - self["red"] = Label(_("Remove Plugins")) - self["green"] = Label(_("Download Plugins")) + self["red"] = Label() + self["green"] = Label() self.list = [] self["list"] = PluginList(self.list) - self["actions"] = ActionMap(["WizardActions", "ColorActions"], + self["actions"] = ActionMap(["WizardActions"], { "ok": self.save, "back": self.close, + }) + self["PluginDownloadActions"] = ActionMap(["ColorActions"], + { "red": self.delete, "green": self.download }) + self["PluginDownloadActions"].setEnabled(False) self.onFirstExecBegin.append(self.checkWarnings) self.onShown.append(self.updateList) @@ -47,7 +51,6 @@ class PluginBrowser(Screen): self.session.open(MessageBox, text = text, type = MessageBox.TYPE_WARNING) def save(self): - #self.close() self.run() def run(self): @@ -58,7 +61,15 @@ class PluginBrowser(Screen): self.pluginlist = plugins.getPlugins(PluginDescriptor.WHERE_PLUGINMENU) self.list = [PluginEntryComponent(plugin) for plugin in self.pluginlist] self["list"].l.setList(self.list) - + if fileExists(resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/plugin.py")): + self["red"].setText("") + self["green"].setText("") + self["PluginDownloadActions"].setEnabled(False) + else: + self["red"].setText(_("Remove Plugins")) + self["green"].setText(_("Download Plugins")) + self["PluginDownloadActions"].setEnabled(True) + def delete(self): self.session.openWithCallback(self.PluginDownloadBrowserClosed, PluginDownloadBrowser, PluginDownloadBrowser.REMOVE) diff --git a/lib/service/servicedvb.cpp b/lib/service/servicedvb.cpp index b5e2651f..c7bb5d99 100644 --- a/lib/service/servicedvb.cpp +++ b/lib/service/servicedvb.cpp @@ -1387,7 +1387,14 @@ RESULT eDVBServicePlay::setTrickmode(int trick) RESULT eDVBServicePlay::isCurrentlySeekable() { - return m_is_pvr || m_timeshift_active; + int ret = 0; + if (m_decoder) + { + ret = (m_is_pvr || m_timeshift_active) ? 3 : 0; // fast forward/backward possible and seeking possible + if (m_decoder->getVideoProgressive() == -1) + ret &= ~2; + } + return ret; } RESULT eDVBServicePlay::frontendInfo(ePtr &ptr) @@ -2260,9 +2267,7 @@ void eDVBServicePlay::switchToLive() m_timeshift_active = 0; m_timeshift_changed = 1; - m_event((iPlayableService*)this, evSeekableStatusChanged); - - updateDecoder(); + updateDecoder(true); } void eDVBServicePlay::switchToTimeshift() @@ -2292,14 +2297,13 @@ void eDVBServicePlay::switchToTimeshift() eDebug("eDVBServicePlay::switchToTimeshift, in pause mode now."); pause(); - updateDecoder(); /* mainly to switch off PCR, and to set pause */ - - m_event((iPlayableService*)this, evSeekableStatusChanged); + updateDecoder(true); /* mainly to switch off PCR, and to set pause */ } -void eDVBServicePlay::updateDecoder() +void eDVBServicePlay::updateDecoder(bool sendSeekableStateChanged) { int vpid = -1, vpidtype = -1, pcrpid = -1, tpid = -1, achannel = -1, ac3_delay=-1, pcm_delay=-1; + bool mustPlay = false; eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler; @@ -2380,17 +2384,17 @@ void eDVBServicePlay::updateDecoder() Py_DECREF(subs); } } - m_decoder->play(); /* pids will be set later */ } if (m_cue) m_cue->setDecodingDemux(m_decode_demux, m_decoder); - m_decoder->play(); /* pids will be set later. */ + mustPlay = true; } m_timeshift_changed = 0; if (m_decoder) { + bool wasSeekable = m_decoder->getVideoProgressive() != -1; if (m_dvb_service) { achannel = m_dvb_service->getCacheEntry(eDVBService::cACHANNEL); @@ -2449,7 +2453,11 @@ void eDVBServicePlay::updateDecoder() m_decoder->setRadioPic(radio_pic); } - m_decoder->set(); + if (mustPlay) + m_decoder->play(); + else + m_decoder->set(); + m_decoder->setAudioChannel(achannel); /* don't worry about non-existing services, nor pvr services */ @@ -2461,8 +2469,13 @@ void eDVBServicePlay::updateDecoder() m_dvb_service->setCacheEntry(eDVBService::cPCRPID, pcrpid); m_dvb_service->setCacheEntry(eDVBService::cTPID, tpid); } + if (!sendSeekableStateChanged && (m_decoder->getVideoProgressive() != -1) != wasSeekable) + sendSeekableStateChanged = true; } m_have_video_pid = (vpid > 0 && vpid < 0x2000); + + if (sendSeekableStateChanged) + m_event((iPlayableService*)this, evSeekableStatusChanged); } void eDVBServicePlay::loadCuesheet() diff --git a/lib/service/servicedvb.h b/lib/service/servicedvb.h index e3c7fd58..42647b92 100644 --- a/lib/service/servicedvb.h +++ b/lib/service/servicedvb.h @@ -230,7 +230,7 @@ private: void switchToLive(); void switchToTimeshift(); - void updateDecoder(); + void updateDecoder(bool sendSeekableStateChanged=false); int m_skipmode; int m_fastforward; diff --git a/lib/service/servicemp3.cpp b/lib/service/servicemp3.cpp index d3eaa262..2c84f7be 100644 --- a/lib/service/servicemp3.cpp +++ b/lib/service/servicemp3.cpp @@ -189,6 +189,25 @@ int eStaticServiceMP3Info::getLength(const eServiceReference &ref) return -1; } +int eStaticServiceMP3Info::getInfo(const eServiceReference &ref, int w) +{ + switch (w) + { + case iServiceInformation::sTimeCreate: + { + struct stat s; + if(stat(ref.path.c_str(), &s) == 0) + { + return s.st_mtime; + } + return iServiceInformation::resNA; + } + default: break; + } + return iServiceInformation::resNA; +} + + // eServiceMP3 int eServiceMP3::ac3_delay, eServiceMP3::pcm_delay; @@ -640,7 +659,31 @@ RESULT eServiceMP3::setTrickmode(int trick) RESULT eServiceMP3::isCurrentlySeekable() { - return 1; + int ret = 3; // seeking and fast/slow winding possible + GstElement *sink; + + if (!m_gst_playbin) + return 0; + if (m_state != stRunning) + return 0; + + g_object_get (G_OBJECT (m_gst_playbin), "video-sink", &sink, NULL); + + // disable fast winding yet when a dvbvideosink or dvbaudiosink is used + // for this we must do some changes on different places.. (gstreamer.. our sinks.. enigma2) + if (sink) { + ret &= ~2; // only seeking possible + gst_object_unref(sink); + } + else { + g_object_get (G_OBJECT (m_gst_playbin), "audio-sink", &sink, NULL); + if (sink) { + ret &= ~2; // only seeking possible + gst_object_unref(sink); + } + } + + return ret; } RESULT eServiceMP3::info(ePtr&i) diff --git a/lib/service/servicemp3.h b/lib/service/servicemp3.h index 985179f6..56a068b9 100644 --- a/lib/service/servicemp3.h +++ b/lib/service/servicemp3.h @@ -41,6 +41,7 @@ class eStaticServiceMP3Info: public iStaticServiceInformation public: RESULT getName(const eServiceReference &ref, std::string &name); int getLength(const eServiceReference &ref); + int getInfo(const eServiceReference &ref, int w); }; typedef struct _GstElement GstElement; diff --git a/lib/service/servicexine.cpp b/lib/service/servicexine.cpp index 44e6a6e0..6b9adfb9 100644 --- a/lib/service/servicexine.cpp +++ b/lib/service/servicexine.cpp @@ -315,7 +315,7 @@ RESULT eServiceXine::setTrickmode(int trick) RESULT eServiceXine::isCurrentlySeekable() { - return 1; + return 3; } RESULT eServiceXine::info(ePtr&i) diff --git a/tools/genmetaindex.py b/tools/genmetaindex.py index 82e79616..f7dc5b98 100755 --- a/tools/genmetaindex.py +++ b/tools/genmetaindex.py @@ -24,7 +24,7 @@ for file in sys.argv[2:]: assert info for i in info[:]: - if i.tag not in ["name", "packagename", "shortdescription"]: + if i.tag not in ["name", "packagename", "packagetype", "shortdescription"]: info.remove(i) for i in info[:]: