Merge commit 'origin/bug_351_softwaremanager_save_config_before_backup' into experimental
[enigma2.git] / 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, 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(_("Remove Plugins"))
26                 self["green"] = Label(_("Download Plugins"))
27                 
28                 self.list = []
29                 self["list"] = PluginList(self.list)
30                 
31                 self["actions"] = ActionMap(["WizardActions", "ColorActions"],
32                 {
33                         "ok": self.save,
34                         "back": self.close,
35                         "red": self.delete,
36                         "green": self.download
37                 })
38                 self.onFirstExecBegin.append(self.checkWarnings)
39                 self.onShown.append(self.updateList)
40         
41         def checkWarnings(self):
42                 if len(plugins.warnings):
43                         text = _("Some plugins are not available:\n")
44                         for (pluginname, error) in plugins.warnings:
45                                 text += _("%s (%s)\n") % (pluginname, error)
46                         plugins.resetWarnings()
47                         self.session.open(MessageBox, text = text, type = MessageBox.TYPE_WARNING)
48
49         def save(self):
50                 #self.close()
51                 self.run()
52         
53         def run(self):
54                 plugin = self["list"].l.getCurrentSelection()[0]
55                 plugin(session=self.session)
56                 
57         def updateList(self):
58                 self.pluginlist = plugins.getPlugins(PluginDescriptor.WHERE_PLUGINMENU)
59                 self.list = [PluginEntryComponent(plugin) for plugin in self.pluginlist]
60                 self["list"].l.setList(self.list)
61
62         def delete(self):
63                 self.session.openWithCallback(self.PluginDownloadBrowserClosed, PluginDownloadBrowser, PluginDownloadBrowser.REMOVE)
64         
65         def download(self):
66                 self.session.openWithCallback(self.PluginDownloadBrowserClosed, PluginDownloadBrowser, PluginDownloadBrowser.DOWNLOAD)
67
68         def PluginDownloadBrowserClosed(self):
69                 self.updateList()
70                 self.checkWarnings()
71
72
73 class PluginDownloadBrowser(Screen):
74         DOWNLOAD = 0
75         REMOVE = 1
76         lastDownloadDate = None
77
78         def __init__(self, session, type):
79                 Screen.__init__(self, session)
80                 
81                 self.type = type
82                 
83                 self.container = eConsoleAppContainer()
84                 self.container.appClosed.append(self.runFinished)
85                 self.container.dataAvail.append(self.dataAvail)
86                 self.onLayoutFinish.append(self.startRun)
87                 self.onShown.append(self.setWindowTitle)
88                 
89                 self.list = []
90                 self["list"] = PluginList(self.list)
91                 self.pluginlist = []
92                 self.expanded = []
93                 self.installedplugins = []
94                 
95                 if self.type == self.DOWNLOAD:
96                         self["text"] = Label(_("Downloading plugin information. Please wait..."))
97                 elif self.type == self.REMOVE:
98                         self["text"] = Label(_("Getting plugin information. Please wait..."))
99                 
100                 self.run = 0
101
102                 self.remainingdata = ""
103
104                 self["actions"] = ActionMap(["WizardActions"], 
105                 {
106                         "ok": self.go,
107                         "back": self.close,
108                 })
109                 
110         def go(self):
111                 sel = self["list"].l.getCurrentSelection()
112
113                 if sel is None:
114                         return
115
116                 sel = sel[0]
117                 if isinstance(sel, str): # category
118                         if sel in self.expanded:
119                                 self.expanded.remove(sel)
120                         else:
121                                 self.expanded.append(sel)
122                         self.updateList()
123                 else:
124                         if self.type == self.DOWNLOAD:
125                                 self.session.openWithCallback(self.runInstall, MessageBox, _("Do you really want to download\nthe plugin \"%s\"?") % sel.name)
126                         elif self.type == self.REMOVE:
127                                 self.session.openWithCallback(self.runInstall, MessageBox, _("Do you really want to REMOVE\nthe plugin \"%s\"?") % sel.name)
128
129         def runInstall(self, val):
130                 if val:
131                         if self.type == self.DOWNLOAD:
132                                 self.session.openWithCallback(self.installFinished, Console, cmdlist = ["ipkg install " + "enigma2-plugin-" + self["list"].l.getCurrentSelection()[0].name])
133                         elif self.type == self.REMOVE:
134                                 self.session.openWithCallback(self.installFinished, Console, cmdlist = ["ipkg remove " + "enigma2-plugin-" + self["list"].l.getCurrentSelection()[0].name])
135
136         def setWindowTitle(self):
137                 if self.type == self.DOWNLOAD:
138                         self.setTitle(_("Downloadable new plugins"))
139                 elif self.type == self.REMOVE:
140                         self.setTitle(_("Remove plugins"))
141
142         def startIpkgListInstalled(self):
143                 self.container.execute("ipkg list_installed enigma2-plugin-*")
144
145         def startIpkgListAvailable(self):
146                 self.container.execute("ipkg list enigma2-plugin-*")
147
148         def startRun(self):
149                 self["list"].instance.hide()
150                 if self.type == self.DOWNLOAD:
151                         if not PluginDownloadBrowser.lastDownloadDate or (time() - PluginDownloadBrowser.lastDownloadDate) > 3600:
152                                 # Only update from internet once per hour
153                                 self.container.execute("ipkg update")
154                                 PluginDownloadBrowser.lastDownloadDate = time()
155                         else:
156                                 self.startIpkgListAvailable()
157                 elif self.type == self.REMOVE:
158                         self.run = 1
159                         self.startIpkgListInstalled()
160
161         def installFinished(self):
162                 plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
163                 self.container.appClosed.remove(self.runFinished)
164                 self.container.dataAvail.remove(self.dataAvail)
165                 self.close()
166
167         def runFinished(self, retval):
168                 self.remainingdata = ""
169                 if self.run == 0:
170                         self.run = 1
171                         if self.type == self.DOWNLOAD:
172                                 self.startIpkgListInstalled()
173                 elif self.run == 1 and self.type == self.DOWNLOAD:
174                         self.run = 2
175                         self.startIpkgListAvailable()
176                 else:
177                         if len(self.pluginlist) > 0:
178                                 self.updateList()
179                                 self["list"].instance.show()
180                         else:
181                                 self["text"].setText("No new plugins found")
182
183         def dataAvail(self, str):
184                 #prepend any remaining data from the previous call
185                 str = self.remainingdata + str
186                 #split in lines
187                 lines = str.split('\n')
188                 #'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
189                 if len(lines[-1]):
190                         #remember this data for next time
191                         self.remainingdata = lines[-1]
192                         lines = lines[0:-1]
193                 else:
194                         self.remainingdata = ""
195
196                 for x in lines:
197                         plugin = x.split(" - ", 2)
198                         if len(plugin) == 3:
199                                 if self.run == 1 and self.type == self.DOWNLOAD:
200                                         if plugin[0] not in self.installedplugins:
201                                                 self.installedplugins.append(plugin[0])
202                                 else:
203                                         if plugin[0] not in self.installedplugins:
204                                                 plugin.append(plugin[0][15:])
205
206                                                 self.pluginlist.append(plugin)
207         
208         def updateList(self):
209                 list = []
210                 expandableIcon = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/expandable-plugins.png"))
211                 expandedIcon = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/expanded-plugins.png"))
212                 verticallineIcon = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/verticalline-plugins.png"))
213                 
214                 self.plugins = {}
215                 for x in self.pluginlist:
216                         split = x[3].split('-', 1)
217                         if len(split) < 2:
218                                 continue
219                         if not self.plugins.has_key(split[0]):
220                                 self.plugins[split[0]] = []
221                                 
222                         self.plugins[split[0]].append((PluginDescriptor(name = x[3], description = x[2], icon = verticallineIcon), split[1]))
223                         
224                 for x in self.plugins.keys():
225                         if x in self.expanded:
226                                 list.append(PluginCategoryComponent(x, expandedIcon))
227                                 list.extend([PluginDownloadComponent(plugin[0], plugin[1]) for plugin in self.plugins[x]])
228                         else:
229                                 list.append(PluginCategoryComponent(x, expandableIcon))
230                 self.list = list
231                 self["list"].l.setList(list)
232
233 language.addCallback(languageChanged)