Support turbo2.
[vuplus_dvbapp] / lib / python / Screens / PluginBrowser.py
1 from Screen import Screen
2 from Components.Language import language
3 from enigma import eConsoleAppContainer
4
5 from Components.ActionMap import ActionMap
6 from Components.PluginComponent import plugins
7 from Components.PluginList import *
8 from Components.Label import Label
9 from Screens.MessageBox import MessageBox
10 from Screens.Console import Console
11 from Plugins.Plugin import PluginDescriptor
12 from Tools.Directories import resolveFilename, fileExists, SCOPE_PLUGINS, SCOPE_SKIN_IMAGE
13 from Tools.LoadPixmap import LoadPixmap
14
15 from time import time
16
17 def languageChanged():
18         plugins.clearPluginList()
19         plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
20
21 class PluginBrowser(Screen):
22         def __init__(self, session):
23                 Screen.__init__(self, session)
24                 
25                 self["red"] = Label()
26                 self["green"] = Label()
27                 
28                 self.list = []
29                 self["list"] = PluginList(self.list)
30                 
31                 self["actions"] = ActionMap(["WizardActions"],
32                 {
33                         "ok": self.save,
34                         "back": self.close,
35                 })
36                 self["PluginDownloadActions"] = ActionMap(["ColorActions"],
37                 {
38                         "red": self.delete,
39                         "green": self.download
40                 })
41                 self["SoftwareActions"] = ActionMap(["ColorActions"],
42                 {
43                         "red": self.openExtensionmanager
44                 })
45                 self["PluginDownloadActions"].setEnabled(False)
46                 self["SoftwareActions"].setEnabled(False)
47                 self.onFirstExecBegin.append(self.checkWarnings)
48                 self.onShown.append(self.updateList)
49                 self.onLayoutFinish.append(self.saveListsize)
50
51         def saveListsize(self):
52                 listsize = self["list"].instance.size()
53                 self.listWidth = listsize.width()
54                 self.listHeight = listsize.height()
55         
56         def checkWarnings(self):
57                 if len(plugins.warnings):
58                         text = _("Some plugins are not available:\n")
59                         for (pluginname, error) in plugins.warnings:
60                                 text += _("%s (%s)\n") % (pluginname, error)
61                         plugins.resetWarnings()
62                         self.session.open(MessageBox, text = text, type = MessageBox.TYPE_WARNING)
63
64         def save(self):
65                 self.run()
66         
67         def run(self):
68                 plugin = self["list"].l.getCurrentSelection()[0]
69                 plugin(session=self.session)
70                 
71         def updateList(self):
72                 self.pluginlist = plugins.getPlugins(PluginDescriptor.WHERE_PLUGINMENU)
73                 self.list = [PluginEntryComponent(plugin, self.listWidth) for plugin in self.pluginlist]
74                 self["list"].l.setList(self.list)
75                 if fileExists(resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/plugin.py")):
76                         self["red"].setText(_("Manage extensions"))
77                         self["green"].setText("")
78                         self["SoftwareActions"].setEnabled(True)
79                         self["PluginDownloadActions"].setEnabled(False)
80                 else:
81                         self["red"].setText(_("Remove Plugins"))
82                         self["green"].setText(_("Download Plugins"))
83                         self["SoftwareActions"].setEnabled(False)
84                         self["PluginDownloadActions"].setEnabled(True)
85                         
86         def delete(self):
87                 self.session.openWithCallback(self.PluginDownloadBrowserClosed, PluginDownloadBrowser, PluginDownloadBrowser.REMOVE)
88         
89         def download(self):
90                 self.session.openWithCallback(self.PluginDownloadBrowserClosed, PluginDownloadBrowser, PluginDownloadBrowser.DOWNLOAD)
91
92         def PluginDownloadBrowserClosed(self):
93                 self.updateList()
94                 self.checkWarnings()
95
96         def openExtensionmanager(self):
97                 if fileExists(resolveFilename(SCOPE_PLUGINS, "SystemPlugins/SoftwareManager/plugin.py")):
98                         try:
99                                 from Plugins.SystemPlugins.SoftwareManager.plugin import PluginManager
100                         except ImportError:
101                                 self.session.open(MessageBox, _("The Softwaremanagement extension is not installed!\nPlease install it."), type = MessageBox.TYPE_INFO,timeout = 10 )
102                         else:
103                                 self.session.openWithCallback(self.PluginDownloadBrowserClosed, PluginManager)
104
105 class PluginDownloadBrowser(Screen):
106         DOWNLOAD = 0
107         REMOVE = 1
108         lastDownloadDate = None
109
110         def __init__(self, session, type):
111                 Screen.__init__(self, session)
112                 
113                 self.type = type
114                 
115                 self.container = eConsoleAppContainer()
116                 self.container.appClosed.append(self.runFinished)
117                 self.container.dataAvail.append(self.dataAvail)
118                 self.onLayoutFinish.append(self.startRun)
119                 self.onShown.append(self.setWindowTitle)
120                 
121                 self.list = []
122                 self["list"] = PluginList(self.list)
123                 self.pluginlist = []
124                 self.expanded = []
125                 self.installedplugins = []
126                 
127                 if self.type == self.DOWNLOAD:
128                         self["text"] = Label(_("Downloading plugin information. Please wait..."))
129                 elif self.type == self.REMOVE:
130                         self["text"] = Label(_("Getting plugin information. Please wait..."))
131                 
132                 self.run = 0
133
134                 self.remainingdata = ""
135
136                 self["actions"] = ActionMap(["WizardActions"], 
137                 {
138                         "ok": self.go,
139                         "back": self.close,
140                 })
141                 
142         def go(self):
143                 sel = self["list"].l.getCurrentSelection()
144
145                 if sel is None:
146                         return
147
148                 sel = sel[0]
149                 if isinstance(sel, str): # category
150                         if sel in self.expanded:
151                                 self.expanded.remove(sel)
152                         else:
153                                 self.expanded.append(sel)
154                         self.updateList()
155                 else:
156                         if self.type == self.DOWNLOAD:
157                                 self.session.openWithCallback(self.runInstall, MessageBox, _("Do you really want to download\nthe plugin \"%s\"?") % sel.name)
158                         elif self.type == self.REMOVE:
159                                 self.session.openWithCallback(self.runInstall, MessageBox, _("Do you really want to REMOVE\nthe plugin \"%s\"?") % sel.name)
160
161         def runInstall(self, val):
162                 if val:
163                         if self.type == self.DOWNLOAD:
164                                 self.session.openWithCallback(self.installFinished, Console, cmdlist = ["opkg install " + "enigma2-plugin-" + self["list"].l.getCurrentSelection()[0].name])
165                         elif self.type == self.REMOVE:
166                                 self.session.openWithCallback(self.installFinished, Console, cmdlist = ["opkg remove " + "enigma2-plugin-" + self["list"].l.getCurrentSelection()[0].name])
167
168         def setWindowTitle(self):
169                 if self.type == self.DOWNLOAD:
170                         self.setTitle(_("Downloadable new plugins"))
171                 elif self.type == self.REMOVE:
172                         self.setTitle(_("Remove plugins"))
173
174         def startIpkgListInstalled(self):
175                 self.container.execute("opkg list_installed enigma2-plugin-*")
176
177         def startIpkgListAvailable(self):
178                 self.container.execute("opkg list enigma2-plugin-*")
179
180         def startRun(self):
181                 listsize = self["list"].instance.size()
182                 self["list"].instance.hide()
183                 self.listWidth = listsize.width()
184                 self.listHeight = listsize.height()
185                 if self.type == self.DOWNLOAD:
186                         if not PluginDownloadBrowser.lastDownloadDate or (time() - PluginDownloadBrowser.lastDownloadDate) > 3600:
187                                 # Only update from internet once per hour
188                                 self.container.execute("opkg update")
189                                 PluginDownloadBrowser.lastDownloadDate = time()
190                         else:
191                                 self.startIpkgListAvailable()
192                 elif self.type == self.REMOVE:
193                         self.run = 1
194                         self.startIpkgListInstalled()
195
196         def installFinished(self):
197                 plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
198                 self.container.appClosed.remove(self.runFinished)
199                 self.container.dataAvail.remove(self.dataAvail)
200                 self.close()
201
202         def runFinished(self, retval):
203                 self.remainingdata = ""
204                 if self.run == 0:
205                         self.run = 1
206                         if self.type == self.DOWNLOAD:
207                                 self.startIpkgListInstalled()
208                 elif self.run == 1 and self.type == self.DOWNLOAD:
209                         self.run = 2
210                         self.startIpkgListAvailable()
211                 else:
212                         if len(self.pluginlist) > 0:
213                                 self.updateList()
214                                 self["list"].instance.show()
215                         else:
216                                 self["text"].setText("No new plugins found")
217
218         def dataAvail(self, str):
219                 #prepend any remaining data from the previous call
220                 str = self.remainingdata + str
221                 #split in lines
222                 lines = str.split('\n')
223                 #'str' should end with '\n', so when splitting, the last line should be empty. If this is not the case, we received an incomplete line
224                 if len(lines[-1]):
225                         #remember this data for next time
226                         self.remainingdata = lines[-1]
227                         lines = lines[0:-1]
228                 else:
229                         self.remainingdata = ""
230
231                 for x in lines:
232                         plugin = x.split(" - ")
233                         if len(plugin) >= 2:
234                                 if self.run == 1 and self.type == self.DOWNLOAD:
235                                         if plugin[0] not in self.installedplugins:
236                                                 self.installedplugins.append(plugin[0])
237                                 else:
238                                         if plugin[0] not in self.installedplugins:
239                                                 plugin.append(plugin[0][15:])
240
241                                                 self.pluginlist.append(plugin)
242         
243         def updateList(self):
244                 list = []
245                 expandableIcon = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/expandable-plugins.png"))
246                 expandedIcon = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/expanded-plugins.png"))
247                 verticallineIcon = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/verticalline-plugins.png"))
248                 
249                 self.plugins = {}
250                 for x in self.pluginlist:
251                         if len(x) < 4:
252                                 split = x[0].split('-',3)
253                                 if not self.plugins.has_key(split[2]):
254                                         self.plugins[split[2]] = []
255                                 self.plugins[split[2]].append((PluginDescriptor(name = x[2], description = " ", icon = verticallineIcon), split[3]))
256                                 continue
257
258                         split = x[3].split('-', 1)
259                         if len(split) < 2:
260                                 continue
261                         if not self.plugins.has_key(split[0]):
262                                 self.plugins[split[0]] = []
263                                 
264                         self.plugins[split[0]].append((PluginDescriptor(name = x[3], description = x[2], icon = verticallineIcon), split[1]))
265                         
266                 for x in self.plugins.keys():
267                         if x in self.expanded:
268                                 list.append(PluginCategoryComponent(x, expandedIcon, self.listWidth))
269                                 list.extend([PluginDownloadComponent(plugin[0], plugin[1], self.listWidth) for plugin in self.plugins[x]])
270                         else:
271                                 list.append(PluginCategoryComponent(x, expandableIcon, self.listWidth))
272                 self.list = list
273                 self["list"].l.setList(list)
274
275 language.addCallback(languageChanged)