lib/python/Plugins/SystemPlugins/SoftwareManager: more robust code this i.e. fixes:
[enigma2.git] / lib / python / Plugins / SystemPlugins / SoftwareManager / SoftwareTools.py
1 from enigma import eConsoleAppContainer
2 from Components.Console import Console
3 from Components.About import about
4 from Components.DreamInfoHandler import DreamInfoHandler
5 from Components.Language import language
6 from Components.Sources.List import List
7 from Components.Ipkg import IpkgComponent
8 from Components.Network import iNetwork
9 from Tools.Directories import pathExists, fileExists, resolveFilename, SCOPE_METADIR
10
11 from time import time
12
13 class SoftwareTools(DreamInfoHandler):
14         lastDownloadDate = None
15         NetworkConnectionAvailable = None
16         list_updating = False
17         available_updates = 0
18         available_updatelist  = []
19         available_packetlist  = []
20         installed_packetlist = {}
21
22         
23         def __init__(self):
24                 aboutInfo = about.getImageVersionString()
25                 if aboutInfo.startswith("dev-"):
26                         self.ImageVersion = 'Experimental'
27                 else:
28                         self.ImageVersion = 'Stable'
29                 self.language = language.getLanguage()[:2] # getLanguage returns e.g. "fi_FI" for "language_country"
30                 DreamInfoHandler.__init__(self, self.statusCallback, blocking = False, neededTag = 'ALL_TAGS', neededFlag = self.ImageVersion, language = self.language)
31                 self.directory = resolveFilename(SCOPE_METADIR)
32                 self.list = List([])
33                 self.NotifierCallback = None
34                 self.Console = Console()
35                 self.UpdateConsole = Console()
36                 self.cmdList = []
37                 self.unwanted_extensions = ('-dbg', '-dev', '-doc')
38                 self.ipkg = IpkgComponent()
39                 self.ipkg.addCallback(self.ipkgCallback)                
40
41         def statusCallback(self, status, progress):
42                 pass            
43
44         def startSoftwareTools(self, callback = None):
45                 if callback is not None:
46                         self.NotifierCallback = callback
47                 iNetwork.checkNetworkState(self.checkNetworkCB)
48                 
49         def checkNetworkCB(self,data):
50                 if data is not None:
51                         if data <= 2:
52                                 SoftwareTools.NetworkConnectionAvailable = True
53                                 self.getUpdates()
54                         else:
55                                 SoftwareTools.NetworkConnectionAvailable = False
56                                 self.getUpdates()
57
58         def getUpdates(self, callback = None):
59                 if SoftwareTools.NetworkConnectionAvailable == True:
60                         SoftwareTools.lastDownloadDate = time()
61                         if SoftwareTools.list_updating is False and callback is None:
62                                 SoftwareTools.list_updating = True
63                                 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
64                         elif SoftwareTools.list_updating is False and callback is not None:
65                                 SoftwareTools.list_updating = True
66                                 self.NotifierCallback = callback
67                                 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
68                         elif SoftwareTools.list_updating is True and callback is not None:
69                                 #update info collecting already in progress
70                                 self.NotifierCallback = callback
71                 else:
72                         SoftwareTools.list_updating = False
73                         if callback is not None:
74                                 callback(False)
75                         elif self.NotifierCallback is not None:
76                                 self.NotifierCallback(False)
77
78         def ipkgCallback(self, event, param):
79                 if event == IpkgComponent.EVENT_ERROR:
80                         SoftwareTools.list_updating = False
81                 elif event == IpkgComponent.EVENT_DONE:
82                         if SoftwareTools.list_updating:
83                                 self.startIpkgListAvailable()
84                 pass
85
86         def startIpkgListAvailable(self, callback = None):
87                 if callback is not None:
88                         SoftwareTools.list_updating = True
89                 if SoftwareTools.list_updating:
90                         if not self.UpdateConsole:
91                                 self.UpdateConsole = Console()
92                         cmd = "ipkg list"
93                         self.UpdateConsole.ePopen(cmd, self.IpkgListAvailableCB, callback)
94
95         def IpkgListAvailableCB(self, result, retval, extra_args = None):
96                 (callback) = extra_args
97                 if result:
98                         if SoftwareTools.list_updating:
99                                 SoftwareTools.available_packetlist = []
100                                 for x in result.splitlines():
101                                         tokens = x.split(' - ')
102                                         name = tokens[0].strip()
103                                         if not any(name.endswith(x) for x in self.unwanted_extensions):
104                                                 l = len(tokens)
105                                                 version = l > 1 and tokens[1].strip() or ""
106                                                 descr = l > 2 and tokens[2].strip() or ""
107                                                 SoftwareTools.available_packetlist.append([name, version, descr])
108                                 if callback is None:
109                                         self.startInstallMetaPackage()
110                                 else:
111                                         if self.UpdateConsole:
112                                                 if len(self.UpdateConsole.appContainers) == 0:
113                                                                 callback(True)
114                 else:
115                         SoftwareTools.list_updating = False
116                         if self.UpdateConsole:
117                                 if len(self.UpdateConsole.appContainers) == 0:
118                                         if callback is not None:
119                                                 callback(False)
120
121         def startInstallMetaPackage(self, callback = None):
122                 if callback is not None:
123                         SoftwareTools.list_updating = True
124                 if SoftwareTools.list_updating:
125                         if not self.UpdateConsole:
126                                 self.UpdateConsole = Console()
127                         cmd = "ipkg install enigma2-meta enigma2-plugins-meta enigma2-skins-meta"
128                         self.UpdateConsole.ePopen(cmd, self.InstallMetaPackageCB, callback)
129
130         def InstallMetaPackageCB(self, result, retval, extra_args = None):
131                 (callback) = extra_args
132                 if result:
133                         self.fillPackagesIndexList()
134                         if callback is None:
135                                 self.startIpkgListInstalled()
136                         else:
137                                 if self.UpdateConsole:
138                                         if len(self.UpdateConsole.appContainers) == 0:
139                                                         callback(True)
140                 else:
141                         SoftwareTools.list_updating = False
142                         if self.UpdateConsole:
143                                 if len(self.UpdateConsole.appContainers) == 0:
144                                         if callback is not None:
145                                                 callback(False)
146
147         def startIpkgListInstalled(self, callback = None):
148                 if callback is not None:
149                         SoftwareTools.list_updating = True
150                 if SoftwareTools.list_updating:
151                         if not self.UpdateConsole:
152                                 self.UpdateConsole = Console()
153                         cmd = "ipkg list_installed"
154                         self.UpdateConsole.ePopen(cmd, self.IpkgListInstalledCB, callback)
155
156         def IpkgListInstalledCB(self, result, retval, extra_args = None):
157                 (callback) = extra_args
158                 if result:
159                         SoftwareTools.installed_packetlist = {}
160                         for x in result.splitlines():
161                                 tokens = x.split(' - ')
162                                 name = tokens[0].strip()
163                                 if not any(name.endswith(x) for x in self.unwanted_extensions):
164                                         l = len(tokens)
165                                         version = l > 1 and tokens[1].strip() or ""
166                                         SoftwareTools.installed_packetlist[name] = version
167                         if callback is None:
168                                 self.countUpdates()
169                         else:
170                                 if self.UpdateConsole:
171                                         if len(self.UpdateConsole.appContainers) == 0:
172                                                         callback(True)
173                 else:
174                         SoftwareTools.list_updating = False
175                         if self.UpdateConsole:
176                                 if len(self.UpdateConsole.appContainers) == 0:
177                                         if callback is not None:
178                                                 callback(False)
179
180         def countUpdates(self, callback = None):
181                 SoftwareTools.available_updates = 0
182                 SoftwareTools.available_updatelist  = []
183                 for package in self.packagesIndexlist[:]:
184                         attributes = package[0]["attributes"]
185                         packagename = attributes["packagename"]
186                         for x in SoftwareTools.available_packetlist:
187                                 if x[0] == packagename:
188                                         if SoftwareTools.installed_packetlist.has_key(packagename):
189                                                 if SoftwareTools.installed_packetlist[packagename] != x[1]:
190                                                         SoftwareTools.available_updates +=1
191                                                         SoftwareTools.available_updatelist.append([packagename])
192
193                 SoftwareTools.list_updating = False
194                 if self.UpdateConsole:
195                         if len(self.UpdateConsole.appContainers) == 0:
196                                 if callback is not None:
197                                         callback(True)
198                                         callback = None
199                                 elif self.NotifierCallback is not None:
200                                         self.NotifierCallback(True)
201                                         self.NotifierCallback = None
202
203         def startIpkgUpdate(self, callback = None):
204                 if not self.Console:
205                         self.Console = Console()
206                 cmd = "ipkg update"
207                 self.Console.ePopen(cmd, self.IpkgUpdateCB, callback)
208
209         def IpkgUpdateCB(self, result, retval, extra_args = None):
210                 (callback) = extra_args
211                 if result:
212                         if self.Console:
213                                 if len(self.Console.appContainers) == 0:
214                                         if callback is not None:
215                                                 callback(True)
216                                                 callback = None
217
218         def cleanupSoftwareTools(self):
219                 if self.NotifierCallback is not None:
220                         self.NotifierCallback = None
221                 self.ipkg.stop()
222                 if self.Console is not None:
223                         if len(self.Console.appContainers):
224                                 for name in self.Console.appContainers.keys():
225                                         self.Console.kill(name)
226                 if self.UpdateConsole is not None:
227                         if len(self.UpdateConsole.appContainers):
228                                 for name in self.UpdateConsole.appContainers.keys():
229                                         self.UpdateConsole.kill(name)
230
231 iSoftwareTools = SoftwareTools()