some ipkg changes.. (done by ritzmo)
[enigma2.git] / lib / python / Plugins / SystemPlugins / SoftwareUpdate / plugin.py
1 from Components.ActionMap import ActionMap, NumberActionMap
2 from Components.GUIComponent import GUIComponent
3 from Components.Input import Input
4 from Components.Ipkg import IpkgComponent
5 from Components.Label import Label
6 from Components.MenuList import MenuList
7 from Components.Slider import Slider
8 from Plugins.Plugin import PluginDescriptor
9 from Screens.Console import Console
10 from Screens.ImageWizard import ImageWizard
11 from Screens.MessageBox import MessageBox
12 from Screens.MessageBox import MessageBox
13 from Screens.Screen import Screen
14 from enigma import eTimer, quitMainloop, RT_HALIGN_LEFT, RT_VALIGN_CENTER, eListboxPythonMultiContent, eListbox, gFont
15 from os import popen
16
17
18 class UpdatePluginMenu(Screen):
19         skin = """
20                 <screen position="200,100" size="300,250" title="Update..." >
21                         <widget name="menu" position="10,10" size="290,175" scrollbarMode="showOnDemand" />
22                 </screen>"""
23                 
24         def __init__(self, session, args = 0):
25                 self.skin = UpdatePluginMenu.skin
26                 Screen.__init__(self, session)
27                 
28                 self.menu = args
29                 
30                 list = []
31                 if self.menu == 0:
32                         list.append((_("Image-Upgrade"), "image"))
33                         list.append((_("Online-Upgrade"), "upgrade"))
34                         list.append((_("Advanced"), "advanced"))
35                 elif self.menu == 1:
36                         list.append((_("Choose source"), "source"))
37                         list.append((_("Packet management"), "ipkg"))
38                         list.append((_("Settings"), "setup"))
39                 
40                 self["menu"] = MenuList(list)
41                                 
42                 self["actions"] = ActionMap(["WizardActions", "DirectionActions"], 
43                 {
44                         "ok": self.go,
45                         "back": self.close,
46                 }, -1)
47                 
48         def go(self):
49                 if self.menu == 0:
50                         if (self["menu"].l.getCurrentSelection()[1] == "image"):
51                                 self.session.open(ImageWizard)
52                         if (self["menu"].l.getCurrentSelection()[1] == "upgrade"):
53                                 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to update your Dreambox?\nAfter pressing OK, please wait!"))
54                         if (self["menu"].l.getCurrentSelection()[1] == "advanced"):
55                                 self.session.open(UpdatePluginMenu, 1)
56                 if self.menu == 1:
57                         if (self["menu"].l.getCurrentSelection()[1] == "source"):
58                                 self.session.open(IPKGSource)
59                         elif (self["menu"].l.getCurrentSelection()[1] == "ipkg"):
60                                 self.session.open(Ipkg)
61                         elif (self["menu"].l.getCurrentSelection()[1] == "setup"):
62                                 self.session.open(MessageBox, _("Function not yet implemented"), MessageBox.TYPE_ERROR)
63         
64         def runUpgrade(self, result):
65                 if result:
66                         self.session.open(Console, title = "Upgrade running...", cmdlist = ["ipkg update", "ipkg upgrade -force-defaults -force-overwrite"], finishedCallback = self.runFinished)
67
68         def runFinished(self):
69                 self.session.openWithCallback(self.reboot, MessageBox, _("Upgrade finished. Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
70                 
71         def reboot(self, result):
72                 if result is None:
73                         return
74                 if result:
75                         quitMainloop(3)
76
77 class IPKGSource(Screen):
78         skin = """
79                 <screen position="100,100" size="550,60" title="IPKG source" >
80                         <widget name="text" position="0,0" size="550,25" font="Regular;20" />
81                 </screen>"""
82                 
83         def __init__(self, session, args = None):
84                 self.skin = IPKGSource.skin
85                 Screen.__init__(self, session)
86                 
87                 fp = file('/etc/ipkg/official-feed.conf', 'r')
88                 sources = fp.readlines()
89                 fp.close()
90                 
91                 self["text"] = Input(sources[0], maxSize=False, type=Input.TEXT)
92                                 
93                 self["actions"] = NumberActionMap(["WizardActions", "InputActions"], 
94                 {
95                         "ok": self.go,
96                         "back": self.close,
97                         "left": self.keyLeft,
98                         "right": self.keyRight,
99                         "1": self.keyNumberGlobal,
100                         "2": self.keyNumberGlobal,
101                         "3": self.keyNumberGlobal,
102                         "4": self.keyNumberGlobal,
103                         "5": self.keyNumberGlobal,
104                         "6": self.keyNumberGlobal,
105                         "7": self.keyNumberGlobal,
106                         "8": self.keyNumberGlobal,
107                         "9": self.keyNumberGlobal,
108                         "0": self.keyNumberGlobal
109                 }, -1)
110                 
111         def go(self):
112                 fp = file('/etc/ipkg/official-feed.conf', 'w')
113                 fp.write(self["text"].getText())
114                 fp.close()
115                 self.close()
116                 
117         def keyLeft(self):
118                 self["text"].left()
119         
120         def keyRight(self):
121                 self["text"].right()
122         
123         def keyNumberGlobal(self, number):
124                 print "pressed", number
125                 self["text"].number(number)
126
127 def PacketEntryComponent(packet):
128         res = [ packet ]
129         
130         res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 0,250, 30, 0, RT_HALIGN_LEFT|RT_VALIGN_CENTER, packet[0]))
131         res.append((eListboxPythonMultiContent.TYPE_TEXT, 250, 0, 200, 30, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, packet[1]))
132         res.append((eListboxPythonMultiContent.TYPE_TEXT, 450, 0, 100, 30, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, packet[2]))
133         return res
134
135 class PacketList(GUIComponent):
136         def __init__(self, list):
137                 GUIComponent.__init__(self)
138                 self.l = eListboxPythonMultiContent()
139                 self.l.setList(list)
140                 self.l.setFont(0, gFont("Regular", 20))
141                 self.l.setFont(1, gFont("Regular", 18))
142         
143         def getCurrent(self):
144                 return self.l.getCurrentSelection()
145         
146         def GUIcreate(self, parent):
147                 self.instance = eListbox(parent)
148                 self.instance.setContent(self.l)
149                 self.instance.setItemHeight(30)
150         
151         def GUIdelete(self):
152                 self.instance.setContent(None)
153                 self.instance = None
154
155         def invalidate(self):
156                 self.l.invalidate()
157
158 class Ipkg2(Screen):
159         skin = """
160                 <screen position="100,100" size="550,400" title="IPKG upgrade..." >
161                         <widget name="list" position="0,0" size="550,400" scrollbarMode="showOnDemand" />
162                 </screen>"""
163                 
164         def __init__(self, session, args = None):
165                 self.skin = Ipkg.skin
166                 Screen.__init__(self, session)
167         
168                 list = []
169                 self.list = list
170                 self.fillPacketList()
171
172                 self["list"] = PacketList(self.list)
173                                 
174                 self["actions"] = ActionMap(["WizardActions"], 
175                 {
176                         "ok": self.close,
177                         "back": self.close
178                 }, -1)
179                 
180
181         def fillPacketList(self):
182                 lines = popen("ipkg list", "r").readlines()
183                 packetlist = []
184                 for x in lines:
185                         split = x.split(' - ')
186                         packetlist.append([split[0].strip(), split[1].strip()])
187                 
188                 lines = popen("ipkg list_installed", "r").readlines()
189                 
190                 installedlist = {}
191                 for x in lines:
192                         split = x.split(' - ')
193                         installedlist[split[0].strip()] = split[1].strip()
194                 
195                 for x in packetlist:
196                         status = ""
197                         if installedlist.has_key(x[0]):
198                                 if installedlist[x[0]] == x[1]:
199                                         status = "installed"
200                                 else:
201                                         status = "upgradable"
202                         self.list.append(PacketEntryComponent([x[0], x[1], status]))
203                 
204         def go(self):
205                 if self.update:
206                         self.session.openWithCallback(self.doUpdate, MessageBox, _("Do you want to update your Dreambox?\nAfter pressing OK, please wait!"))            
207                 else:
208                         self.close()
209         
210         def doUpdateDelay(self):
211                 lines = popen("ipkg update && ipkg upgrade", "r").readlines()
212                 string = ""
213                 for x in lines:
214                         string += x
215                 self["text"].setText(_("Updating finished. Here is the result:") + "\n\n" + string)
216                 self.update = False
217                         
218         
219         def doUpdate(self, val = False):
220                 if val == True:
221                         self["text"].setText(_("Updating... Please wait... This can take some minutes..."))
222                         self.delayTimer.start(0, 1)
223                 else:
224                         self.close()
225                         
226 class UpdatePlugin(Screen):
227         skin = """
228                 <screen position="100,100" size="550,200" title="Software Update..." >
229                         <widget name="activityslider" position="0,0" size="550,5"  />
230                         <widget name="slider" position="0,100" size="550,30"  />
231                         <widget name="package" position="10,30" size="540,20" font="Regular;18"/>
232                         <widget name="status" position="10,60" size="540,45" font="Regular;18"/>
233                 </screen>"""
234                 
235         def __init__(self, session, args = None):
236                 self.skin = UpdatePlugin.skin
237                 Screen.__init__(self, session)
238                 
239                 self.sliderPackages = { "dreambox-dvb-modules": 1, "enigma2": 2, "tuxbox-image-info": 3 }
240                 
241                 self.slider = Slider(0, 4)
242                 self["slider"] = self.slider
243                 self.activityslider = Slider(0, 100)
244                 self["activityslider"] = self.activityslider
245                 self.status = Label(_("Upgrading Dreambox... Please wait"))
246                 self["status"] = self.status
247                 self.package = Label()
248                 self["package"] = self.package
249                 
250                 self.packages = 0
251                 self.error = 0
252                 
253                 self.activity = 0
254                 self.activityTimer = eTimer()
255                 self.activityTimer.timeout.get().append(self.doActivityTimer)
256                 self.activityTimer.start(100, False)
257                                 
258                 self.ipkg = IpkgComponent()
259                 self.ipkg.addCallback(self.ipkgCallback)
260                 
261                 self.updating = True
262                 self.package.setText(_("Package list update"))
263                 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
264                         
265                 self["actions"] = ActionMap(["WizardActions"], 
266                 {
267                         "ok": self.exit,
268                         "back": self.exit
269                 }, -1)
270                 
271         def doActivityTimer(self):
272                 self.activity += 1
273                 if self.activity == 100:
274                         self.activity = 0
275                 self.activityslider.setValue(self.activity)
276                 
277         def ipkgCallback(self, event, param):
278                 if event == IpkgComponent.EVENT_DOWNLOAD:
279                         self.status.setText(_("Downloading"))
280                 elif event == IpkgComponent.EVENT_UPGRADE:
281                         if self.sliderPackages.has_key(param):
282                                 self.slider.setValue(self.sliderPackages[param])
283                         self.package.setText(param)
284                         self.status.setText(_("Upgrading"))
285                         self.packages += 1
286                 elif event == IpkgComponent.EVENT_INSTALL:
287                         self.package.setText(param)
288                         self.status.setText(_("Installing"))
289                         self.packages += 1
290                 elif event == IpkgComponent.EVENT_CONFIGURING:
291                         self.package.setText(param)
292                         self.status.setText(_("Configuring"))
293                 elif event == IpkgComponent.EVENT_MODIFIED:
294                         self.session.openWithCallback(
295                                 self.modificationCallback,
296                                 MessageBox,
297                                 _("A configuration file (%s) was modified since Installation.\nDo you want to keep your version?") % (param)
298                         )
299                 elif event == IpkgComponent.EVENT_ERROR:
300                         self.error += 1
301                 elif event == IpkgComponent.EVENT_DONE:
302                         if self.updating:
303                                 self.updating = False
304                                 self.ipkg.startCmd(IpkgComponent.CMD_UPGRADE, args = {'test_only': False})
305                         elif self.error == 0:
306                                 self.slider.setValue(4)
307                                 
308                                 self.activityTimer.stop()
309                                 self.activityslider.setValue(0)
310                                 
311                                 self.package.setText("")
312                                 self.status.setText(_("Done - Installed or upgraded %d packages") % self.packages)
313                         else:
314                                 self.activityTimer.stop()
315                                 self.activityslider.setValue(0)
316                                 error = _("your dreambox might be unusable now. Please consult the manual for further assistance before rebooting your dreambox.")
317                                 if self.packages == 0:
318                                         error = _("No packages were upgraded yet. So you can check your network and try again.")
319                                 if self.updating:
320                                         error = _("Your dreambox isn't connected to the internet properly. Please check it and try again.")
321                                 self.status.setText(_("Error") +  " - " + error)
322                 #print event, "-", param
323                 pass
324
325         def modificationCallback(self, res):
326                 self.ipkg.write(res and "N" or "Y")
327
328         def exit(self):
329                 if not self.ipkg.isRunning():
330                         if self.packages != 0 and self.error == 0:
331                                 self.session.openWithCallback(self.exitAnswer, MessageBox, _("Upgrade finished. Do you want to reboot your Dreambox?"))
332                         else:
333                                 self.close()
334                         
335         def exitAnswer(self, result):
336                 if result is not None and result:
337                         quitMainloop(2)
338                 self.close()
339
340 def UpgradeMain(session, **kwargs):
341         session.open(UpdatePlugin)
342
343 def Plugins(**kwargs):
344         return PluginDescriptor(name="Softwareupdate", description=_("Updates your receiver's software"), icon="update.png", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=UpgradeMain)