fix merge conflict.
[vuplus_dvbapp] / lib / python / Plugins / SystemPlugins / WirelessLan / plugin.py
1 from Plugins.Plugin import PluginDescriptor
2 from Screens.Console import Console
3 from Screens.ChoiceBox import ChoiceBox
4 from Screens.MessageBox import MessageBox
5 from Screens.Screen import Screen
6 from Screens.Ipkg import Ipkg
7 from Components.ActionMap import ActionMap, NumberActionMap
8 from Components.Input import Input
9 from Components.Ipkg import IpkgComponent
10 from Components.Sources.StaticText import StaticText
11 from Components.ScrollLabel import ScrollLabel
12 from Components.Pixmap import Pixmap
13 from Components.MenuList import MenuList
14 from Components.Sources.List import List
15 from Components.Slider import Slider
16 from Components.Harddisk import harddiskmanager
17 from Components.config import config,getConfigListEntry, ConfigSubsection, ConfigText, ConfigLocations
18 from Components.Console import Console
19 from Components.MultiContent import MultiContentEntryText, MultiContentEntryPixmapAlphaTest
20 from Components.SelectionList import SelectionList
21 from Components.PluginComponent import plugins
22 from Components.About import about
23 from Components.DreamInfoHandler import DreamInfoHandler
24 from Components.Language import language
25 from Components.AVSwitch import AVSwitch
26 from Tools.Directories import pathExists, fileExists, resolveFilename, SCOPE_PLUGINS, SCOPE_CURRENT_PLUGIN, SCOPE_CURRENT_SKIN, SCOPE_METADIR
27 from Tools.LoadPixmap import LoadPixmap
28 from enigma import eTimer, quitMainloop, RT_HALIGN_LEFT, RT_VALIGN_CENTER, eListboxPythonMultiContent, eListbox, gFont, getDesktop, ePicLoad
29 from cPickle import dump, load
30 from os import path as os_path, system as os_system, unlink, stat, mkdir, popen, makedirs, listdir, access, rename, remove, W_OK, R_OK, F_OK
31 from time import time, gmtime, strftime, localtime
32 from stat import ST_MTIME
33 from datetime import date
34 from twisted.web import client
35 from twisted.internet import reactor
36
37 from ImageWizard import ImageWizard
38 from BackupRestore import BackupSelection, RestoreMenu, BackupScreen, RestoreScreen, getBackupPath, getBackupFilename
39 #from SoftwareTools import extensions
40
41 config.plugins.configurationbackup = ConfigSubsection()
42 config.plugins.configurationbackup.backuplocation = ConfigText(default = '/media/hdd/', visible_width = 50, fixed_size = False)
43 config.plugins.configurationbackup.backupdirs = ConfigLocations(default=['/etc/enigma2/', '/etc/network/interfaces', '/etc/wpa_supplicant.conf', '/etc/resolv.conf', '/etc/default_gw', '/etc/hostname'])
44
45 def write_cache(cache_file, cache_data):
46         #Does a cPickle dump
47         if not os_path.isdir( os_path.dirname(cache_file) ):
48                 try:
49                         mkdir( os_path.dirname(cache_file) )
50                 except OSError:
51                             print os_path.dirname(cache_file), 'is a file'
52         fd = open(cache_file, 'w')
53         dump(cache_data, fd, -1)
54         fd.close()
55
56 def valid_cache(cache_file, cache_ttl):
57         #See if the cache file exists and is still living
58         try:
59                 mtime = stat(cache_file)[ST_MTIME]
60         except:
61                 return 0
62         curr_time = time()
63         if (curr_time - mtime) > cache_ttl:
64                 return 0
65         else:
66                 return 1
67
68 def load_cache(cache_file):
69         #Does a cPickle load
70         fd = open(cache_file)
71         cache_data = load(fd)
72         fd.close()
73         return cache_data
74
75
76 class UpdatePluginMenu(Screen):
77         skin = """
78                 <screen name="UpdatePluginMenu" position="center,center" size="560,400" title="Software manager" >
79                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
80                         <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
81                         <ePixmap pixmap="skin_default/border_menu_300.png" position="5,50" zPosition="1" size="300,300" transparent="1" alphatest="on" />
82                         <widget source="menu" render="Listbox" position="10,60" size="290,260" scrollbarMode="showOnDemand">
83                                 <convert type="TemplatedMultiContent">
84                                         {"template": [
85                                                         MultiContentEntryText(pos = (2, 2), size = (290, 22), flags = RT_HALIGN_LEFT, text = 1), # index 0 is the MenuText,
86                                                 ],
87                                         "fonts": [gFont("Regular", 20)],
88                                         "itemHeight": 25
89                                         }
90                                 </convert>
91                         </widget>
92                         <widget source="menu" render="Listbox" position="310,50" size="240,300" scrollbarMode="showNever" selectionDisabled="1">
93                                 <convert type="TemplatedMultiContent">
94                                         {"template": [
95                                                         MultiContentEntryText(pos = (2, 2), size = (240, 300), flags = RT_HALIGN_CENTER|RT_VALIGN_CENTER|RT_WRAP, text = 2), # index 2 is the Description,
96                                                 ],
97                                         "fonts": [gFont("Regular", 20)],
98                                         "itemHeight": 300
99                                         }
100                                 </convert>
101                         </widget>
102                 </screen>"""
103                 
104         def __init__(self, session, args = 0):
105                 Screen.__init__(self, session)
106                 self.skin_path = plugin_path
107                 self.menu = args
108                 self.list = []
109                 self.oktext = _("\nPress OK on your remote control to continue.")
110                 self.backupdirs = ' '.join( config.plugins.configurationbackup.backupdirs.value )
111                 if self.menu == 0:
112                         self.list.append(("software-update", _("Software update"), _("\nOnline update of your Dreambox software." ) + self.oktext, None))
113                         self.list.append(("install-plugins", _("Install extensions"), _("\nInstall new Extensions or Plugins to your dreambox" ) + self.oktext, None))
114                         self.list.append(("software-restore", _("Software restore"), _("\nRestore your Dreambox with a new firmware." ) + self.oktext, None))
115                         self.list.append(("system-backup", _("Backup system settings"), _("\nBackup your Dreambox settings." ) + self.oktext, None))
116                         self.list.append(("system-restore",_("Restore system settings"), _("\nRestore your Dreambox settings." ) + self.oktext, None))
117                         self.list.append(("ipkg-install", _("Install local extension"),  _("\nScan for local packages and install them." ) + self.oktext, None))
118                         for p in plugins.getPlugins(PluginDescriptor.WHERE_SOFTWAREMANAGER):
119                                 if p.__call__.has_key("SoftwareSupported"):
120                                         callFnc = p.__call__["SoftwareSupported"](None)
121                                         if callFnc is not None:
122                                                 if p.__call__.has_key("menuEntryName"):
123                                                         menuEntryName = p.__call__["menuEntryName"](None)
124                                                 else:
125                                                         menuEntryName = _('Extended Software')
126                                                 if p.__call__.has_key("menuEntryDescription"):
127                                                         menuEntryDescription = p.__call__["menuEntryDescription"](None)
128                                                 else:
129                                                         menuEntryDescription = _('Extended Software Plugin')
130                                                 self.list.append(('default-plugin', menuEntryName, menuEntryDescription + self.oktext, callFnc))
131                         if config.usage.setup_level.index >= 2: # expert+
132                                 self.list.append(("advanced", _("Advanced Options"), _("\nAdvanced options and settings." ) + self.oktext, None))
133                 elif self.menu == 1:
134                         self.list.append(("advancedrestore", _("Advanced restore"), _("\nRestore your backups by date." ) + self.oktext, None))
135                         self.list.append(("backuplocation", _("Choose backup location"),  _("\nSelect your backup device.\nCurrent device: " ) + config.plugins.configurationbackup.backuplocation.value + self.oktext, None))
136                         self.list.append(("backupfiles", _("Choose backup files"),  _("Select files for backup. Currently selected:\n" ) + self.backupdirs + self.oktext, None))
137                         if config.usage.setup_level.index >= 2: # expert+
138                                 self.list.append(("ipkg-manager", _("Packet management"),  _("\nView, install and remove available or installed packages." ) + self.oktext, None))
139                         self.list.append(("ipkg-source",_("Choose upgrade source"), _("\nEdit the upgrade source address." ) + self.oktext, None))
140                         for p in plugins.getPlugins(PluginDescriptor.WHERE_SOFTWAREMANAGER):
141                                 if p.__call__.has_key("AdvancedSoftwareSupported"):
142                                         callFnc = p.__call__["AdvancedSoftwareSupported"](None)
143                                         if callFnc is not None:
144                                                 if p.__call__.has_key("menuEntryName"):
145                                                         menuEntryName = p.__call__["menuEntryName"](None)
146                                                 else:
147                                                         menuEntryName = _('Advanced Software')
148                                                 if p.__call__.has_key("menuEntryDescription"):
149                                                         menuEntryDescription = p.__call__["menuEntryDescription"](None)
150                                                 else:
151                                                         menuEntryDescription = _('Advanced Software Plugin')
152                                                 self.list.append(('advanced-plugin', menuEntryName, menuEntryDescription + self.oktext, callFnc))
153
154                 self["menu"] = List(self.list)
155                 self["key_red"] = StaticText(_("Close"))
156
157                 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
158                 {
159                         "ok": self.go,
160                         "back": self.close,
161                         "red": self.close,
162                 }, -1)
163
164                 self.onLayoutFinish.append(self.layoutFinished)
165                 self.backuppath = getBackupPath()
166                 self.backupfile = getBackupFilename()
167                 self.fullbackupfilename = self.backuppath + "/" + self.backupfile
168                 self.onShown.append(self.setWindowTitle)
169
170         def layoutFinished(self):
171                 idx = 0
172                 self["menu"].index = idx
173
174         def setWindowTitle(self):
175                 self.setTitle(_("Software manager"))
176
177         def go(self):
178                 current = self["menu"].getCurrent()
179                 if current:
180                         currentEntry = current[0]
181                         if self.menu == 0:
182                                 if (currentEntry == "software-update"):
183                                         self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to update your Dreambox?")+"\n"+_("\nAfter pressing OK, please wait!"))
184                                 elif (currentEntry == "software-restore"):
185                                         self.session.open(ImageWizard)
186                                 elif (currentEntry == "install-plugins"):
187                                         self.session.open(PluginManager, self.skin_path)
188                                 elif (currentEntry == "system-backup"):
189                                         self.session.openWithCallback(self.backupDone,BackupScreen, runBackup = True)
190                                 elif (currentEntry == "system-restore"):
191                                         if os_path.exists(self.fullbackupfilename):
192                                                 self.session.openWithCallback(self.startRestore, MessageBox, _("Are you sure you want to restore your Enigma2 backup?\nEnigma2 will restart after the restore"))
193                                         else:
194                                                 self.session.open(MessageBox, _("Sorry no backups found!"), MessageBox.TYPE_INFO, timeout = 10)
195                                 elif (currentEntry == "ipkg-install"):
196                                         try:
197                                                 from Plugins.Extensions.MediaScanner.plugin import main
198                                                 main(self.session)
199                                         except:
200                                                 self.session.open(MessageBox, _("Sorry MediaScanner is not installed!"), MessageBox.TYPE_INFO, timeout = 10)
201                                 elif (currentEntry == "default-plugin"):
202                                         self.extended = current[3]
203                                         self.extended(self.session, None)
204                                 elif (currentEntry == "advanced"):
205                                         self.session.open(UpdatePluginMenu, 1)
206                         elif self.menu == 1:
207                                 if (currentEntry == "ipkg-manager"):
208                                         self.session.open(PacketManager, self.skin_path)
209                                 elif (currentEntry == "backuplocation"):
210                                         parts = [ (r.description, r.mountpoint, self.session) for r in harddiskmanager.getMountedPartitions(onlyhotplug = False)]
211                                         for x in parts:
212                                                 if not access(x[1], F_OK|R_OK|W_OK) or x[1] == '/':
213                                                         parts.remove(x)
214                                         for x in parts:
215                                                 if x[1].startswith('/autofs/'):
216                                                         parts.remove(x)
217                                         if len(parts):
218                                                 self.session.openWithCallback(self.backuplocation_choosen, ChoiceBox, title = _("Please select medium to use as backup location"), list = parts)
219                                 elif (currentEntry == "backupfiles"):
220                                         self.session.openWithCallback(self.backupfiles_choosen,BackupSelection)
221                                 elif (currentEntry == "advancedrestore"):
222                                         self.session.open(RestoreMenu, self.skin_path)
223                                 elif (currentEntry == "ipkg-source"):
224                                         self.session.open(IPKGMenu, self.skin_path)
225                                 elif (currentEntry == "advanced-plugin"):
226                                         self.extended = current[3]
227                                         self.extended(self.session, None)
228
229         def backupfiles_choosen(self, ret):
230                 self.backupdirs = ' '.join( config.plugins.configurationbackup.backupdirs.value )
231
232         def backuplocation_choosen(self, option):
233                 if option is not None:
234                         config.plugins.configurationbackup.backuplocation.value = str(option[1])
235                 config.plugins.configurationbackup.backuplocation.save()
236                 config.plugins.configurationbackup.save()
237                 config.save()
238                 self.createBackupfolders()
239
240         def runUpgrade(self, result):
241                 if result:
242                         self.session.open(UpdatePlugin, self.skin_path)
243
244         def createBackupfolders(self):
245                 print "Creating backup folder if not already there..."
246                 self.backuppath = getBackupPath()
247                 try:
248                         if (os_path.exists(self.backuppath) == False):
249                                 makedirs(self.backuppath)
250                 except OSError:
251                         self.session.open(MessageBox, _("Sorry, your backup destination is not writeable.\n\nPlease choose another one."), MessageBox.TYPE_INFO, timeout = 10)
252
253         def backupDone(self,retval = None):
254                 if retval is True:
255                         self.session.open(MessageBox, _("Backup done."), MessageBox.TYPE_INFO, timeout = 10)
256                 else:
257                         self.session.open(MessageBox, _("Backup failed."), MessageBox.TYPE_INFO, timeout = 10)
258
259         def startRestore(self, ret = False):
260                 if (ret == True):
261                         self.exe = True
262                         self.session.open(RestoreScreen, runRestore = True)
263
264 class IPKGMenu(Screen):
265         skin = """
266                 <screen name="IPKGMenu" position="center,center" size="560,400" title="Select upgrade source to edit." >
267                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
268                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
269                         <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
270                         <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
271                         <widget name="filelist" position="5,50" size="550,340" scrollbarMode="showOnDemand" />
272                 </screen>"""
273
274         def __init__(self, session, plugin_path):
275                 Screen.__init__(self, session)
276                 self.skin_path = plugin_path
277                 
278                 self["key_red"] = StaticText(_("Close"))
279                 self["key_green"] = StaticText(_("Edit"))
280
281                 self.sel = []
282                 self.val = []
283                 self.entry = False
284                 self.exe = False
285                 
286                 self.path = ""
287
288                 self["actions"] = NumberActionMap(["SetupActions"],
289                 {
290                         "ok": self.KeyOk,
291                         "cancel": self.keyCancel
292                 }, -1)
293
294                 self["shortcuts"] = ActionMap(["ShortcutActions"],
295                 {
296                         "red": self.keyCancel,
297                         "green": self.KeyOk,
298                 })
299                 self.flist = []
300                 self["filelist"] = MenuList(self.flist)
301                 self.fill_list()
302                 self.onLayoutFinish.append(self.layoutFinished)
303
304         def layoutFinished(self):
305                 self.setWindowTitle()
306
307         def setWindowTitle(self):
308                 self.setTitle(_("Select upgrade source to edit."))
309
310         def fill_list(self):
311                 self.flist = []
312                 self.path = '/etc/ipkg/'
313                 if (os_path.exists(self.path) == False):
314                         self.entry = False
315                         return
316                 for file in listdir(self.path):
317                         if (file.endswith(".conf")):
318                                 if file != 'arch.conf':
319                                         self.flist.append((file))
320                                         self.entry = True
321                                         self["filelist"].l.setList(self.flist)
322
323         def KeyOk(self):
324                 if (self.exe == False) and (self.entry == True):
325                         self.sel = self["filelist"].getCurrent()
326                         self.val = self.path + self.sel
327                         self.session.open(IPKGSource, self.val)
328
329         def keyCancel(self):
330                 self.close()
331
332         def Exit(self):
333                 self.close()
334
335
336 class IPKGSource(Screen):
337         skin = """
338                 <screen name="IPKGSource" position="center,center" size="560,80" title="Edit upgrade source url." >
339                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
340                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
341                         <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
342                         <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
343                         <widget name="text" position="5,50" size="550,25" font="Regular;20" backgroundColor="background" foregroundColor="#cccccc" />
344                 </screen>"""
345
346         def __init__(self, session, configfile = None):
347                 Screen.__init__(self, session)
348                 self.session = session
349                 self.configfile = configfile
350                 text = ""
351                 if self.configfile:
352                         try:
353                                 fp = file(configfile, 'r')
354                                 sources = fp.readlines()
355                                 if sources:
356                                         text = sources[0]
357                                 fp.close()
358                         except IOError:
359                                 pass
360
361                 desk = getDesktop(0)
362                 x= int(desk.size().width())
363                 y= int(desk.size().height())
364
365                 self["key_red"] = StaticText(_("Cancel"))
366                 self["key_green"] = StaticText(_("Save"))
367
368                 if (y>=720):
369                         self["text"] = Input(text, maxSize=False, type=Input.TEXT)
370                 else:
371                         self["text"] = Input(text, maxSize=False, visible_width = 55, type=Input.TEXT)
372
373                 self["actions"] = NumberActionMap(["WizardActions", "InputActions", "TextEntryActions", "KeyboardInputActions","ShortcutActions"], 
374                 {
375                         "ok": self.go,
376                         "back": self.close,
377                         "red": self.close,
378                         "green": self.go,
379                         "left": self.keyLeft,
380                         "right": self.keyRight,
381                         "home": self.keyHome,
382                         "end": self.keyEnd,
383                         "deleteForward": self.keyDeleteForward,
384                         "deleteBackward": self.keyDeleteBackward,
385                         "1": self.keyNumberGlobal,
386                         "2": self.keyNumberGlobal,
387                         "3": self.keyNumberGlobal,
388                         "4": self.keyNumberGlobal,
389                         "5": self.keyNumberGlobal,
390                         "6": self.keyNumberGlobal,
391                         "7": self.keyNumberGlobal,
392                         "8": self.keyNumberGlobal,
393                         "9": self.keyNumberGlobal,
394                         "0": self.keyNumberGlobal
395                 }, -1)
396
397                 self.onLayoutFinish.append(self.layoutFinished)
398
399         def layoutFinished(self):
400                 self.setWindowTitle()
401                 self["text"].right()
402
403         def setWindowTitle(self):
404                 self.setTitle(_("Edit upgrade source url."))
405
406         def go(self):
407                 text = self["text"].getText()
408                 if text:
409                         fp = file(self.configfile, 'w')
410                         fp.write(text)
411                         fp.write("\n")
412                         fp.close()
413                 self.close()
414
415         def keyLeft(self):
416                 self["text"].left()
417         
418         def keyRight(self):
419                 self["text"].right()
420         
421         def keyHome(self):
422                 self["text"].home()
423         
424         def keyEnd(self):
425                 self["text"].end()
426         
427         def keyDeleteForward(self):
428                 self["text"].delete()
429         
430         def keyDeleteBackward(self):
431                 self["text"].deleteBackward()
432         
433         def keyNumberGlobal(self, number):
434                 self["text"].number(number)
435
436
437 class PacketManager(Screen):
438         skin = """
439                 <screen name="PacketManager" position="center,center" size="530,420" title="Packet manager" >
440                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
441                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
442                         <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
443                         <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
444                         <widget source="list" render="Listbox" position="5,50" size="520,365" scrollbarMode="showOnDemand">
445                                 <convert type="TemplatedMultiContent">
446                                         {"template": [
447                                                         MultiContentEntryText(pos = (5, 1), size = (440, 28), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name
448                                                         MultiContentEntryText(pos = (5, 26), size = (440, 20), font=1, flags = RT_HALIGN_LEFT, text = 2), # index 2 is the description
449                                                         MultiContentEntryPixmapAlphaTest(pos = (445, 2), size = (48, 48), png = 4), # index 4 is the status pixmap
450                                                         MultiContentEntryPixmapAlphaTest(pos = (5, 50), size = (510, 2), png = 5), # index 4 is the div pixmap
451                                                 ],
452                                         "fonts": [gFont("Regular", 22),gFont("Regular", 14)],
453                                         "itemHeight": 52
454                                         }
455                                 </convert>
456                         </widget>
457                 </screen>"""
458                 
459         def __init__(self, session, plugin_path, args = None):
460                 Screen.__init__(self, session)
461                 self.session = session
462                 self.skin_path = plugin_path
463
464                 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"], 
465                 {
466                         "ok": self.go,
467                         "back": self.exit,
468                         "red": self.exit,
469                         "green": self.reload,
470                 }, -1)
471                 
472                 self.list = []
473                 self.statuslist = []
474                 self["list"] = List(self.list)
475                 self["key_red"] = StaticText(_("Close"))
476                 self["key_green"] = StaticText(_("Reload"))
477
478                 self.list_updating = True
479                 self.packetlist = []
480                 self.installed_packetlist = {}
481                 self.Console = Console()
482                 self.cmdList = []
483                 self.cachelist = []
484                 self.cache_ttl = 86400  #600 is default, 0 disables, Seconds cache is considered valid (24h should be ok for caching ipkgs)
485                 self.cache_file = '/usr/lib/enigma2/python/Plugins/SystemPlugins/SoftwareManager/packetmanager.cache' #Path to cache directory   
486                 self.oktext = _("\nAfter pressing OK, please wait!")
487                 self.unwanted_extensions = ('-dbg', '-dev', '-doc', 'busybox')
488
489                 self.ipkg = IpkgComponent()
490                 self.ipkg.addCallback(self.ipkgCallback)
491                 self.onShown.append(self.setWindowTitle)
492                 self.onLayoutFinish.append(self.rebuildList)
493
494         def exit(self):
495                 self.ipkg.stop()
496                 if self.Console is not None:
497                         if len(self.Console.appContainers):
498                                 for name in self.Console.appContainers.keys():
499                                         self.Console.kill(name)
500                 self.close()
501
502         def reload(self):
503                 if (os_path.exists(self.cache_file) == True):
504                         remove(self.cache_file)
505                         self.list_updating = True
506                         self.rebuildList()
507                         
508         def setWindowTitle(self):
509                 self.setTitle(_("Packet manager"))
510
511         def setStatus(self,status = None):
512                 if status:
513                         self.statuslist = []
514                         divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png"))
515                         if status == 'update':
516                                 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgrade.png"))
517                                 self.statuslist.append(( _("Package list update"), '', _("Trying to download a new packetlist. Please wait..." ),'',statuspng, divpng ))
518                                 self['list'].setList(self.statuslist)   
519                         elif status == 'error':
520                                 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png"))
521                                 self.statuslist.append(( _("Error"), '', _("There was an error downloading the packetlist. Please try again." ),'',statuspng, divpng ))
522                                 self['list'].setList(self.statuslist)                           
523
524         def rebuildList(self):
525                 self.setStatus('update')
526                 self.inv_cache = 0
527                 self.vc = valid_cache(self.cache_file, self.cache_ttl)
528                 if self.cache_ttl > 0 and self.vc != 0:
529                         try:
530                                 self.buildPacketList()
531                         except:
532                                 self.inv_cache = 1
533                 if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0:
534                         self.run = 0
535                         self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
536
537         def go(self, returnValue = None):
538                 cur = self["list"].getCurrent()
539                 if cur:
540                         status = cur[3]
541                         package = cur[0]
542                         self.cmdList = []
543                         if status == 'installed':
544                                 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package }))
545                                 if len(self.cmdList):
546                                         self.session.openWithCallback(self.runRemove, MessageBox, _("Do you want to remove the package:\n") + package + "\n" + self.oktext)
547                         elif status == 'upgradeable':
548                                 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package }))
549                                 if len(self.cmdList):
550                                         self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to upgrade the package:\n") + package + "\n" + self.oktext)
551                         elif status == "installable":
552                                 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package }))
553                                 if len(self.cmdList):
554                                         self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to install the package:\n") + package + "\n" + self.oktext)
555
556         def runRemove(self, result):
557                 if result:
558                         self.session.openWithCallback(self.runRemoveFinished, Ipkg, cmdList = self.cmdList)
559
560         def runRemoveFinished(self):
561                 self.session.openWithCallback(self.RemoveReboot, MessageBox, _("Remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
562
563         def RemoveReboot(self, result):
564                 if result is None:
565                         return
566                 if result is False:
567                         cur = self["list"].getCurrent()
568                         if cur:
569                                 item = self['list'].getIndex()
570                                 self.list[item] = self.buildEntryComponent(cur[0], cur[1], cur[2], 'installable')
571                                 self.cachelist[item] = [cur[0], cur[1], cur[2], 'installable']
572                                 self['list'].setList(self.list)
573                                 write_cache(self.cache_file, self.cachelist)
574                                 self.reloadPluginlist()
575                 if result:
576                         quitMainloop(3)
577
578         def runUpgrade(self, result):
579                 if result:
580                         self.session.openWithCallback(self.runUpgradeFinished, Ipkg, cmdList = self.cmdList)
581
582         def runUpgradeFinished(self):
583                 self.session.openWithCallback(self.UpgradeReboot, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
584                 
585         def UpgradeReboot(self, result):
586                 if result is None:
587                         return
588                 if result is False:
589                         cur = self["list"].getCurrent()
590                         if cur:
591                                 item = self['list'].getIndex()
592                                 self.list[item] = self.buildEntryComponent(cur[0], cur[1], cur[2], 'installed')
593                                 self.cachelist[item] = [cur[0], cur[1], cur[2], 'installed']
594                                 self['list'].setList(self.list)
595                                 write_cache(self.cache_file, self.cachelist)
596                                 self.reloadPluginlist()
597                 if result:
598                         quitMainloop(3)
599
600         def ipkgCallback(self, event, param):
601                 if event == IpkgComponent.EVENT_ERROR:
602                         self.list_updating = False
603                         self.setStatus('error')
604                 elif event == IpkgComponent.EVENT_DONE:
605                         if self.list_updating:
606                                 self.list_updating = False
607                                 if not self.Console:
608                                         self.Console = Console()
609                                 cmd = "ipkg list"
610                                 self.Console.ePopen(cmd, self.IpkgList_Finished)
611                 #print event, "-", param
612                 pass
613
614         def IpkgList_Finished(self, result, retval, extra_args = None):
615                 if len(result):
616                         self.packetlist = []
617                         for x in result.splitlines():
618                                 split = x.split(' - ')   #self.blacklisted_packages
619                                 if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions):
620                                         self.packetlist.append([split[0].strip(), split[1].strip(),split[2].strip()])
621                 if not self.Console:
622                         self.Console = Console()
623                 cmd = "ipkg list_installed"
624                 self.Console.ePopen(cmd, self.IpkgListInstalled_Finished)
625
626         def IpkgListInstalled_Finished(self, result, retval, extra_args = None):
627                 if len(result):
628                         self.installed_packetlist = {}
629                         for x in result.splitlines():
630                                 split = x.split(' - ')
631                                 if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions):
632                                         self.installed_packetlist[split[0].strip()] = split[1].strip()
633                 self.buildPacketList()
634
635         def buildEntryComponent(self, name, version, description, state):
636                 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png"))
637                 if state == 'installed':
638                         installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installed.png"))
639                         return((name, version, description, state, installedpng, divpng))       
640                 elif state == 'upgradeable':
641                         upgradeablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgradeable.png"))
642                         return((name, version, description, state, upgradeablepng, divpng))     
643                 else:
644                         installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installable.png"))
645                         return((name, version, description, state, installablepng, divpng))
646
647         def buildPacketList(self):
648                 self.list = []
649                 self.cachelist = []
650
651                 if self.cache_ttl > 0 and self.vc != 0:
652                         print 'Loading packagelist cache from ',self.cache_file
653                         try:
654                                 self.cachelist = load_cache(self.cache_file)
655                                 if len(self.cachelist) > 0:
656                                         for x in self.cachelist:
657                                                 self.list.append(self.buildEntryComponent(x[0], x[1], x[2], x[3]))
658                                         self['list'].setList(self.list)
659                         except:
660                                 self.inv_cache = 1
661
662                 if self.cache_ttl == 0 or self.inv_cache == 1 or self.vc == 0:
663                         print 'rebuilding fresh package list'
664                         for x in self.packetlist:
665                                 status = ""
666                                 if self.installed_packetlist.has_key(x[0].strip()):
667                                         if self.installed_packetlist[x[0].strip()] == x[1].strip():
668                                                 status = "installed"
669                                                 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status))
670                                         else:
671                                                 status = "upgradeable"
672                                                 self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status))
673                                 else:
674                                         status = "installable"
675                                         self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), status))
676                                 if not any(x[0].strip().endswith(x) for x in self.unwanted_extensions):
677                                         self.cachelist.append([x[0].strip(), x[1].strip(), x[2].strip(), status])
678                         write_cache(self.cache_file, self.cachelist)
679                         self['list'].setList(self.list)
680
681         def reloadPluginlist(self):
682                 plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
683
684
685 class PluginManager(Screen, DreamInfoHandler):
686
687         lastDownloadDate = None
688
689         skin = """
690                 <screen name="PluginManager" position="center,center" size="560,440" title="Plugin manager" >
691                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
692                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
693                         <ePixmap pixmap="skin_default/buttons/yellow.png" position="280,0" size="140,40" alphatest="on" />
694                         <ePixmap pixmap="skin_default/buttons/blue.png" position="420,0" size="140,40" alphatest="on" />
695                         <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
696                         <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
697                         <widget source="key_yellow" render="Label" position="280,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#a08500" transparent="1" />
698                         <widget source="key_blue" render="Label" position="420,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#18188b" transparent="1" />
699                         <widget source="list" render="Listbox" position="5,50" size="550,360" scrollbarMode="showOnDemand">
700                                 <convert type="TemplatedMultiContent">
701                                 {"templates":
702                                         {"default": (51,[
703                                                         MultiContentEntryText(pos = (30, 1), size = (470, 24), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name
704                                                         MultiContentEntryText(pos = (30, 25), size = (470, 20), font=1, flags = RT_HALIGN_LEFT, text = 2), # index 2 is the description
705                                                         MultiContentEntryPixmapAlphaTest(pos = (475, 0), size = (48, 48), png = 5), # index 5 is the status pixmap
706                                                         MultiContentEntryPixmapAlphaTest(pos = (0, 49), size = (550, 2), png = 6), # index 6 is the div pixmap
707                                                 ]),
708                                         "category": (40,[
709                                                         MultiContentEntryText(pos = (30, 0), size = (500, 22), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name
710                                                         MultiContentEntryText(pos = (30, 22), size = (500, 16), font=1, flags = RT_HALIGN_LEFT, text = 1), # index 1 is the description
711                                                         MultiContentEntryPixmapAlphaTest(pos = (0, 38), size = (550, 2), png = 3), # index 3 is the div pixmap
712                                                 ])
713                                         },
714                                         "fonts": [gFont("Regular", 22),gFont("Regular", 16)],
715                                         "itemHeight": 52
716                                 }
717                                 </convert>
718                         </widget>
719                         <widget source="status" render="Label" position="5,410" zPosition="10" size="540,30" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
720                 </screen>"""
721
722         def __init__(self, session, plugin_path, args = None):
723                 Screen.__init__(self, session)
724                 self.session = session
725                 self.skin_path = plugin_path
726                 aboutInfo = about.getImageVersionString()
727                 if aboutInfo.startswith("dev-"):
728                         self.ImageVersion = 'Experimental'
729                 else:
730                         self.ImageVersion = 'Stable'
731                 self.language = language.getLanguage()[:2] # getLanguage returns e.g. "fi_FI" for "language_country"
732
733                 DreamInfoHandler.__init__(self, self.statusCallback, blocking = False, neededTag = 'ALL_TAGS', neededFlag = self.ImageVersion, language = self.language)
734                 self.directory = resolveFilename(SCOPE_METADIR)
735
736                 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions", "InfobarEPGActions", "HelpActions" ],
737                 {
738                         "ok": self.handleCurrent,
739                         "back": self.exit,
740                         "red": self.exit,
741                         "green": self.handleCurrent,
742                         "yellow": self.handleSelected,
743                         "showEventInfo": self.handleSelected,
744                         "displayHelp": self.handleHelp,
745                 }, -1)
746
747                 self.list = []
748                 self.statuslist = []
749                 self.selectedFiles = []
750                 self.categoryList = []
751                 self["list"] = List(self.list)
752                 self["key_red"] = StaticText(_("Close"))
753                 self["key_green"] = StaticText("")
754                 self["key_yellow"] = StaticText("")
755                 self["key_blue"] = StaticText("")
756                 self["status"] = StaticText("")
757
758                 self.list_updating = True
759                 self.packetlist = []
760                 self.installed_packetlist = {}
761                 self.available_packetlist = []
762                 self.available_updates = 0
763                 self.Console = Console()
764                 self.cmdList = []
765                 self.oktext = _("\nAfter pressing OK, please wait!")
766                 self.unwanted_extensions = ('-dbg', '-dev', '-doc')
767
768                 self.ipkg = IpkgComponent()
769                 self.ipkg.addCallback(self.ipkgCallback)
770                 if not self.selectionChanged in self["list"].onSelectionChanged:
771                         self["list"].onSelectionChanged.append(self.selectionChanged)
772
773                 self.currList = ""
774                 self.currentSelectedTag = None
775                 self.currentSelectedIndex = None
776
777                 self.onShown.append(self.setWindowTitle)
778                 self.onLayoutFinish.append(self.rebuildList)
779
780         def setWindowTitle(self):
781                 self.setTitle(_("Plugin manager"))
782
783         def exit(self):
784                 if self.currList == "packages":
785                         self.currList = "category"
786                         self.currentSelectedTag = None
787                         self["list"].style = "category"
788                         self['list'].setList(self.categoryList)
789                         self["list"].setIndex(self.currentSelectedIndex)
790                         self["list"].updateList(self.categoryList)
791                         self.selectionChanged()
792                 else:
793                         self.ipkg.stop()
794                         if self.Console is not None:
795                                 if len(self.Console.appContainers):
796                                         for name in self.Console.appContainers.keys():
797                                                 self.Console.kill(name)
798                         self.prepareInstall()
799                         if len(self.cmdList):
800                                 self.session.openWithCallback(self.runExecute, PluginManagerInfo, self.skin_path, self.cmdList)
801                         else:
802                                 self.close()
803
804         def handleHelp(self):
805                 if self.currList != "status":
806                         self.session.open(PluginManagerHelp, self.skin_path)
807
808         def setState(self,status = None):
809                 if status:
810                         self.currList = "status"
811                         self.statuslist = []
812                         self["key_green"].setText("")
813                         self["key_blue"].setText("")
814                         self["key_yellow"].setText("")
815                         divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png"))
816                         if status == 'update':
817                                 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgrade.png"))
818                                 self.statuslist.append(( _("Package list update"), '', _("Trying to download a new packetlist. Please wait..." ),'', '', statuspng, divpng, None, '' ))
819                                 self["list"].style = "default"
820                                 self['list'].setList(self.statuslist)
821                         elif status == 'sync':
822                                 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgrade.png"))
823                                 self.statuslist.append(( _("Package list update"), '', _("Searching for new installed or removed packages. Please wait..." ),'', '', statuspng, divpng, None, '' ))
824                                 self["list"].style = "default"
825                                 self['list'].setList(self.statuslist)
826                         elif status == 'error':
827                                 statuspng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png"))
828                                 self.statuslist.append(( _("Error"), '', _("There was an error downloading the packetlist. Please try again." ),'', '', statuspng, divpng, None, '' ))
829                                 self["list"].style = "default"
830                                 self['list'].setList(self.statuslist)
831
832         def statusCallback(self, status, progress):
833                 pass
834
835         def selectionChanged(self):
836                 current = self["list"].getCurrent()
837                 self["status"].setText("")
838                 if current:
839                         if self.currList == "packages":
840                                 self["key_red"].setText(_("Back"))
841                                 if current[4] == 'installed':
842                                         self["key_green"].setText(_("Remove"))
843                                 elif current[4] == 'installable':
844                                         self["key_green"].setText(_("Install"))
845                                 elif current[4] == 'remove':
846                                         self["key_green"].setText(_("Undo\nRemove"))
847                                 elif current[4] == 'install':
848                                         self["key_green"].setText(_("Undo\nInstall"))
849                                 self["key_yellow"].setText(_("View details"))
850                                 self["key_blue"].setText("")
851                                 if len(self.selectedFiles) == 0 and self.available_updates is not 0:
852                                         self["status"].setText(_("There are at least ") + str(self.available_updates) + _(" updates available."))
853                                 elif len(self.selectedFiles) is not 0:
854                                         self["status"].setText(str(len(self.selectedFiles)) + _(" packages selected."))
855                                 else:
856                                         self["status"].setText(_("There is nothing to be done."))
857                         elif self.currList == "category":
858                                 self["key_red"].setText(_("Close"))
859                                 self["key_green"].setText("")
860                                 self["key_yellow"].setText("")
861                                 self["key_blue"].setText("")
862                                 if len(self.selectedFiles) == 0 and self.available_updates is not 0:
863                                         self["status"].setText(_("There are at least ") + str(self.available_updates) + _(" updates available."))
864                                         self["key_yellow"].setText(_("Update"))
865                                 elif len(self.selectedFiles) is not 0:
866                                         self["status"].setText(str(len(self.selectedFiles)) + _(" packages selected."))
867                                         self["key_yellow"].setText(_("Process"))
868                                 else:
869                                         self["status"].setText(_("There is nothing to be done."))
870
871         def getSelectionState(self, detailsFile):
872                 for entry in self.selectedFiles:
873                         if entry[0] == detailsFile:
874                                 return True
875                 return False
876
877         def rebuildList(self):
878                 self.setState('update')
879                 if not PluginManager.lastDownloadDate or (time() - PluginManager.lastDownloadDate) > 3600:
880                         # Only update from internet once per hour
881                         PluginManager.lastDownloadDate = time()
882                         print "last update time > 1h"
883                         self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
884                 else:
885                         print "last update time < 1h"
886                         self.startIpkgList()
887
888         def ipkgCallback(self, event, param):
889                 if event == IpkgComponent.EVENT_ERROR:
890                         self.list_updating = False
891                         self.setState('error')
892                 elif event == IpkgComponent.EVENT_DONE:
893                         self.startIpkgList()
894                 pass
895
896         def startIpkgList(self):
897                 if self.list_updating:
898                         if not self.Console:
899                                 self.Console = Console()
900                         cmd = "ipkg list"
901                         self.Console.ePopen(cmd, self.IpkgList_Finished)
902
903         def IpkgList_Finished(self, result, retval, extra_args = None):
904                 if len(result):
905                         self.available_packetlist = []
906                         for x in result.splitlines():
907                                 split = x.split(' - ')
908                                 if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions):
909                                         self.available_packetlist.append([split[0].strip(), split[1].strip(), split[2].strip()])
910                 self.startInstallMetaPackage()
911
912         def startInstallMetaPackage(self):
913                 if self.list_updating:
914                         self.list_updating = False
915                         if not self.Console:
916                                 self.Console = Console()
917                         cmd = "ipkg install enigma2-meta enigma2-plugins-meta enigma2-skins-meta"
918                         self.Console.ePopen(cmd, self.InstallMetaPackage_Finished)
919
920         def InstallMetaPackage_Finished(self, result, retval, extra_args = None):
921                 if len(result):
922                         self.fillPackagesIndexList()
923                 if not self.Console:
924                         self.Console = Console()
925                 self.setState('sync')
926                 cmd = "ipkg list_installed"
927                 self.Console.ePopen(cmd, self.IpkgListInstalled_Finished)
928
929         def IpkgListInstalled_Finished(self, result, retval, extra_args = None):
930                 if len(result):
931                         self.installed_packetlist = {}
932                         for x in result.splitlines():
933                                 split = x.split(' - ')
934                                 if not any(split[0].strip().endswith(x) for x in self.unwanted_extensions):
935                                         self.installed_packetlist[split[0].strip()] = split[1].strip()
936                 self.countUpdates()
937                 if self.currentSelectedTag is None:
938                         self.buildCategoryList()
939                 else:
940                         self.buildPacketList(self.currentSelectedTag)
941
942         def countUpdates(self):
943                 self.available_updates = 0
944                 for package in self.packagesIndexlist[:]:
945                         attributes = package[0]["attributes"]
946                         packagename = attributes["packagename"]
947                         for x in self.available_packetlist:
948                                 if x[0].strip() == packagename:
949                                         if self.installed_packetlist.has_key(packagename):
950                                                 if self.installed_packetlist[packagename] != x[1].strip():
951                                                         self.available_updates +=1
952
953         def handleCurrent(self):
954                 current = self["list"].getCurrent()
955                 if current:
956                         if self.currList == "category":
957                                 self.currentSelectedIndex = self["list"].index
958                                 selectedTag = current[2]
959                                 self.buildPacketList(selectedTag)
960                         elif self.currList == "packages":
961                                 if current[7] is not '':
962                                         idx = self["list"].getIndex()
963                                         detailsFile = self.list[idx][1]
964                                         if self.list[idx][7] == True:
965                                                 for entry in self.selectedFiles:
966                                                         if entry[0] == detailsFile:
967                                                                 self.selectedFiles.remove(entry)
968                                         else:
969                                                 alreadyinList = False
970                                                 for entry in self.selectedFiles:
971                                                         if entry[0] == detailsFile:
972                                                                 alreadyinList = True
973                                                 if not alreadyinList:
974                                                         self.selectedFiles.append((detailsFile,current[4],current[3]))
975                                         if current[4] == 'installed':
976                                                 self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'remove', True)
977                                         elif current[4] == 'installable':
978                                                 self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'install', True)
979                                         elif current[4] == 'remove':
980                                                 self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'installed', False)
981                                         elif current[4] == 'install':
982                                                 self.list[idx] = self.buildEntryComponent(current[0], current[1], current[2], current[3], 'installable',False)
983                                         self["list"].setList(self.list)
984                                         self["list"].setIndex(idx)
985                                         self["list"].updateList(self.list)
986                                         self.selectionChanged()
987
988         def handleSelected(self):
989                 current = self["list"].getCurrent()
990                 if current:
991                         if self.currList == "packages":
992                                 if current[7] is not '':
993                                         detailsfile = self.directory[0] + "/" + current[1]
994                                         if (os_path.exists(detailsfile) == True):
995                                                 self.session.openWithCallback(self.detailsClosed, PluginDetails, self.skin_path, current)
996                                         else:
997                                                 self.session.open(MessageBox, _("Sorry, no Details available!"), MessageBox.TYPE_INFO, timeout = 10)
998                         elif self.currList == "category":
999                                 self.prepareInstall()
1000                                 if len(self.cmdList):
1001                                         self.session.openWithCallback(self.runExecute, PluginManagerInfo, self.skin_path, self.cmdList)
1002
1003         def detailsClosed(self, result):
1004                 if result:
1005                         if not self.Console:
1006                                 self.Console = Console()
1007                         self.setState('sync')
1008                         PluginManager.lastDownloadDate = time()
1009                         self.selectedFiles = []
1010                         cmd = "ipkg update"
1011                         self.Console.ePopen(cmd, self.InstallMetaPackage_Finished)
1012
1013         def buildEntryComponent(self, name, details, description, packagename, state, selected = False):
1014                 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png"))
1015                 if state == 'installed':
1016                         installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installed.png"))
1017                         return((name, details, description, packagename, state, installedpng, divpng, selected))
1018                 elif state == 'installable':
1019                         installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installable.png"))
1020                         return((name, details, description, packagename, state, installablepng, divpng, selected))
1021                 elif state == 'remove':
1022                         removepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png"))
1023                         return((name, details, description, packagename, state, removepng, divpng, selected))
1024                 elif state == 'install':
1025                         installpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/install.png"))
1026                         return((name, details, description, packagename, state, installpng, divpng, selected))
1027
1028         def buildPacketList(self, categorytag = None):
1029                 if categorytag is not None:
1030                         self.currList = "packages"
1031                         self.currentSelectedTag = categorytag
1032                         self.packetlist = []
1033                         for package in self.packagesIndexlist[:]:
1034                                 prerequisites = package[0]["prerequisites"]
1035                                 if prerequisites.has_key("tag"):
1036                                         for foundtag in prerequisites["tag"]:
1037                                                 if categorytag == foundtag:
1038                                                         attributes = package[0]["attributes"]
1039                                                         if attributes.has_key("packagetype"):
1040                                                                 if attributes["packagetype"] == "internal":
1041                                                                         continue
1042                                                                 self.packetlist.append([attributes["name"], attributes["details"], attributes["shortdescription"], attributes["packagename"]])
1043                                                         else:
1044                                                                 self.packetlist.append([attributes["name"], attributes["details"], attributes["shortdescription"], attributes["packagename"]])
1045                         self.list = []
1046                         for x in self.packetlist:
1047                                 status = ""
1048                                 selectState = self.getSelectionState(x[1].strip())
1049                                 if self.installed_packetlist.has_key(x[3].strip()):
1050                                         if selectState == True:
1051                                                 status = "remove"
1052                                         else:
1053                                                 status = "installed"
1054                                         self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), x[3].strip(), status, selected = selectState))
1055                                 else:
1056                                         if selectState == True:
1057                                                 status = "install"
1058                                         else:
1059                                                 status = "installable"
1060                                         self.list.append(self.buildEntryComponent(x[0].strip(), x[1].strip(), x[2].strip(), x[3].strip(), status, selected = selectState))
1061                         if len(self.list):
1062                                 self.list.sort(key=lambda x: x[0])
1063                         self["list"].style = "default"
1064                         self['list'].setList(self.list)
1065                         self["list"].updateList(self.list)
1066                         self.selectionChanged()
1067
1068         def buildCategoryList(self):
1069                 self.currList = "category"
1070                 self.categories = []
1071                 self.categoryList = []
1072                 for package in self.packagesIndexlist[:]:
1073                         prerequisites = package[0]["prerequisites"]
1074                         if prerequisites.has_key("tag"):
1075                                 for foundtag in prerequisites["tag"]:
1076                                         attributes = package[0]["attributes"]
1077                                         if foundtag not in self.categories:
1078                                                 self.categories.append(foundtag)
1079                                                 self.categoryList.append(self.buildCategoryComponent(foundtag))
1080                 self.categoryList.sort(key=lambda x: x[0])
1081                 self["list"].style = "category"
1082                 self['list'].setList(self.categoryList)
1083                 self["list"].updateList(self.categoryList)
1084                 self.selectionChanged()
1085
1086         def buildCategoryComponent(self, tag = None):
1087                 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png"))
1088                 if tag is not None:
1089                         if tag == 'System':
1090                                 return(( _("System"), _("View list of available system extensions" ), tag, divpng ))
1091                         elif tag == 'Skin':
1092                                 return(( _("Skins"), _("View list of available skins" ), tag, divpng ))
1093                         elif tag == 'Recording':
1094                                 return(( _("Recordings"), _("View list of available recording extensions" ), tag, divpng ))
1095                         elif tag == 'Network':
1096                                 return(( _("Network"), _("View list of available networking extensions" ), tag, divpng ))
1097                         elif tag == 'CI':
1098                                 return(( _("CommonInterface"), _("View list of available CommonInterface extensions" ), tag, divpng ))
1099                         elif tag == 'Default':
1100                                 return(( _("Default Settings"), _("View list of available default settings" ), tag, divpng ))
1101                         elif tag == 'SAT':
1102                                 return(( _("Satteliteequipment"), _("View list of available Satteliteequipment extensions." ), tag, divpng ))
1103                         elif tag == 'Software':
1104                                 return(( _("Software"), _("View list of available software extensions" ), tag, divpng ))
1105                         elif tag == 'Multimedia':
1106                                 return(( _("Multimedia"), _("View list of available multimedia extensions." ), tag, divpng ))
1107                         elif tag == 'Display':
1108                                 return(( _("Display and Userinterface"), _("View list of available Display and Userinterface extensions." ), tag, divpng ))
1109                         elif tag == 'EPG':
1110                                 return(( _("Electronic Program Guide"), _("View list of available EPG extensions." ), tag, divpng ))
1111                         elif tag == 'Communication':
1112                                 return(( _("Communication"), _("View list of available communication extensions." ), tag, divpng ))
1113                         else: # dynamically generate non existent tags
1114                                 return(( str(tag), _("View list of available ") + str(tag) + _(" extensions." ), tag, divpng ))
1115
1116         def prepareInstall(self):
1117                 self.cmdList = []
1118                 if self.available_updates > 0:
1119                         self.cmdList.append((IpkgComponent.CMD_UPGRADE, { "test_only": False }))
1120                 if self.selectedFiles and len(self.selectedFiles):
1121                         for plugin in self.selectedFiles:
1122                                 detailsfile = self.directory[0] + "/" + plugin[0]
1123                                 if (os_path.exists(detailsfile) == True):
1124                                         self.fillPackageDetails(plugin[0])
1125                                         self.package = self.packageDetails[0]
1126                                         if self.package[0].has_key("attributes"):
1127                                                 self.attributes = self.package[0]["attributes"]
1128                                         if self.attributes.has_key("package"):
1129                                                 self.packagefiles = self.attributes["package"]
1130                                         if plugin[1] == 'installed':
1131                                                 if self.packagefiles:
1132                                                         for package in self.packagefiles[:]:
1133                                                                 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package["name"] }))
1134                                                 else:
1135                                                         self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": plugin[2] }))
1136                                         else:
1137                                                 if self.packagefiles:
1138                                                         for package in self.packagefiles[:]:
1139                                                                 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package["name"] }))
1140                                                 else:
1141                                                         self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": plugin[2] }))
1142                                 else:
1143                                         if plugin[1] == 'installed':
1144                                                 self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": plugin[2] }))
1145                                         else:
1146                                                 self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": plugin[2] }))
1147
1148         def runExecute(self, result):
1149                 if result:
1150                         self.session.openWithCallback(self.runExecuteFinished, Ipkg, cmdList = self.cmdList)
1151                 else:
1152                         self.close()
1153
1154         def runExecuteFinished(self):
1155                 self.session.openWithCallback(self.ExecuteReboot, MessageBox, _("Install or remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
1156
1157         def ExecuteReboot(self, result):
1158                 if result is None:
1159                         return
1160                 if result is False:
1161                         self.reloadPluginlist()
1162                         self.detailsClosed(True)
1163                 if result:
1164                         quitMainloop(3)
1165
1166         def reloadPluginlist(self):
1167                 plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
1168
1169
1170 class PluginManagerInfo(Screen):
1171         skin = """
1172                 <screen name="PluginManagerInfo" position="center,center" size="560,440" title="Plugin manager activity information" >
1173                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
1174                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
1175                         <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
1176                         <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
1177                         <widget source="list" render="Listbox" position="5,50" size="550,350" scrollbarMode="showOnDemand" selectionDisabled="1">
1178                                 <convert type="TemplatedMultiContent">
1179                                         {"template": [
1180                                                         MultiContentEntryText(pos = (50, 1), size = (150, 24), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name
1181                                                         MultiContentEntryText(pos = (50, 25), size = (540, 24), font=1, flags = RT_HALIGN_LEFT, text = 1), # index 1 is the state
1182                                                         MultiContentEntryPixmapAlphaTest(pos = (0, 1), size = (48, 48), png = 2), # index 2 is the status pixmap
1183                                                         MultiContentEntryPixmapAlphaTest(pos = (0, 49), size = (550, 2), png = 3), # index 3 is the div pixmap
1184                                                 ],
1185                                         "fonts": [gFont("Regular", 22),gFont("Regular", 18)],
1186                                         "itemHeight": 52
1187                                         }
1188                                 </convert>
1189                         </widget>
1190                         <ePixmap pixmap="skin_default/div-h.png" position="0,410" zPosition="10" size="560,2" transparent="1" alphatest="on" />
1191                         <widget source="status" render="Label" position="5,420" zPosition="10" size="550,30" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
1192                 </screen>"""
1193
1194         def __init__(self, session, plugin_path, cmdlist = None):
1195                 Screen.__init__(self, session)
1196                 self.session = session
1197                 self.skin_path = plugin_path
1198                 self.cmdlist = cmdlist
1199
1200                 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
1201                 {
1202                         "ok": self.process,
1203                         "back": self.exit,
1204                         "red": self.exit,
1205                         "green": self.process,
1206                 }, -1)
1207
1208                 self.list = []
1209                 self["list"] = List(self.list)
1210                 self["key_red"] = StaticText(_("Cancel"))
1211                 self["key_green"] = StaticText(_("Continue"))
1212                 self["status"] = StaticText(_("Following tasks will be done after you press continue!"))
1213
1214                 self.onShown.append(self.setWindowTitle)
1215                 self.onLayoutFinish.append(self.rebuildList)
1216
1217         def setWindowTitle(self):
1218                 self.setTitle(_("Plugin manager activity information"))
1219
1220         def rebuildList(self):
1221                 self.list = []
1222                 if self.cmdlist is not None:
1223                         for entry in self.cmdlist:
1224                                 action = ""
1225                                 info = ""
1226                                 cmd = entry[0]
1227                                 if cmd == 0:
1228                                         action = 'install'
1229                                 elif cmd == 2:
1230                                         action = 'remove'
1231                                 else:
1232                                         action = 'upgrade'
1233                                 args = entry[1]
1234                                 if cmd == 0:
1235                                         info = args['package']
1236                                 elif cmd == 2:
1237                                         info = args['package']
1238                                 else:
1239                                         info = _("Dreambox software because updates are available.")
1240
1241                                 self.list.append(self.buildEntryComponent(action,info))
1242                         self['list'].setList(self.list)
1243                         self['list'].updateList(self.list)
1244
1245         def buildEntryComponent(self, action,info):
1246                 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png"))
1247                 upgradepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/upgrade.png"))
1248                 installpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/install.png"))
1249                 removepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png"))
1250                 if action == 'install':
1251                         return(( _('Installing'), info, installpng, divpng))
1252                 elif action == 'remove':
1253                         return(( _('Removing'), info, removepng, divpng))
1254                 else:
1255                         return(( _('Upgrading'), info, upgradepng, divpng))
1256
1257         def exit(self):
1258                 self.close(False)
1259
1260         def process(self):
1261                 self.close(True)
1262
1263
1264 class PluginManagerHelp(Screen):
1265         skin = """
1266                 <screen name="PluginManagerHelp" position="center,center" size="560,440" title="Plugin manager help" >
1267                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
1268                         <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
1269                         <widget source="list" render="Listbox" position="5,50" size="550,350" scrollbarMode="showOnDemand" selectionDisabled="1">
1270                                 <convert type="TemplatedMultiContent">
1271                                         {"template": [
1272                                                         MultiContentEntryText(pos = (50, 1), size = (540, 24), font=0, flags = RT_HALIGN_LEFT, text = 0), # index 0 is the name
1273                                                         MultiContentEntryText(pos = (50, 25), size = (540, 24), font=1, flags = RT_HALIGN_LEFT, text = 1), # index 1 is the state
1274                                                         MultiContentEntryPixmapAlphaTest(pos = (0, 1), size = (48, 48), png = 2), # index 2 is the status pixmap
1275                                                         MultiContentEntryPixmapAlphaTest(pos = (0, 49), size = (550, 2), png = 3), # index 3 is the div pixmap
1276                                                 ],
1277                                         "fonts": [gFont("Regular", 22),gFont("Regular", 18)],
1278                                         "itemHeight": 52
1279                                         }
1280                                 </convert>
1281                         </widget>
1282                         <ePixmap pixmap="skin_default/div-h.png" position="0,410" zPosition="10" size="550,2" transparent="1" alphatest="on" />
1283                         <widget source="status" render="Label" position="5,420" zPosition="10" size="550,30" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
1284                 </screen>"""
1285
1286         def __init__(self, session, plugin_path):
1287                 Screen.__init__(self, session)
1288                 self.session = session
1289                 self.skin_path = plugin_path
1290
1291                 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
1292                 {
1293                         "back": self.exit,
1294                         "red": self.exit,
1295                 }, -1)
1296
1297                 self.list = []
1298                 self["list"] = List(self.list)
1299                 self["key_red"] = StaticText(_("Close"))
1300                 self["status"] = StaticText(_("A small overview of the available icon states and actions."))
1301
1302                 self.onShown.append(self.setWindowTitle)
1303                 self.onLayoutFinish.append(self.rebuildList)
1304
1305         def setWindowTitle(self):
1306                 self.setTitle(_("Plugin manager help"))
1307
1308         def rebuildList(self):
1309                 self.list = []
1310                 self.list.append(self.buildEntryComponent('install'))
1311                 self.list.append(self.buildEntryComponent('installable'))
1312                 self.list.append(self.buildEntryComponent('installed'))
1313                 self.list.append(self.buildEntryComponent('remove'))
1314                 self['list'].setList(self.list)
1315                 self['list'].updateList(self.list)
1316
1317         def buildEntryComponent(self, state):
1318                 divpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png"))
1319                 installedpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installed.png"))
1320                 installablepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/installable.png"))
1321                 removepng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/remove.png"))
1322                 installpng = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/install.png"))
1323
1324                 if state == 'installed':
1325                         return(( _('This plugin is installed.'), _('You can remove this plugin.'), installedpng, divpng))
1326                 elif state == 'installable':
1327                         return(( _('This plugin is not installed.'), _('You can install this plugin.'), installablepng, divpng))
1328                 elif state == 'install':
1329                         return(( _('This plugin will be installed.'), _('You can cancel the installation.'), installpng, divpng))
1330                 elif state == 'remove':
1331                         return(( _('This plugin will be removed.'), _('You can cancel the removal.'), removepng, divpng))
1332
1333         def exit(self):
1334                 self.close()
1335
1336
1337 class PluginDetails(Screen, DreamInfoHandler):
1338         skin = """
1339                 <screen name="PluginDetails" position="center,center" size="600,440" title="Plugin details" >
1340                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
1341                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
1342                         <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
1343                         <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
1344                         <widget source="author" render="Label" position="10,50" size="500,25" zPosition="10" font="Regular;21" transparent="1" />
1345                         <widget name="statuspic" position="550,40" size="48,48" alphatest="on"/>
1346                         <widget name="divpic" position="0,80" size="600,2" alphatest="on"/>
1347                         <widget name="detailtext" position="10,90" size="270,330" zPosition="10" font="Regular;21" transparent="1" halign="left" valign="top"/>
1348                         <widget name="screenshot" position="290,90" size="300,330" alphatest="on"/>
1349                 </screen>"""
1350         def __init__(self, session, plugin_path, packagedata = None):
1351                 Screen.__init__(self, session)
1352                 self.skin_path = plugin_path
1353                 self.language = language.getLanguage()[:2] # getLanguage returns e.g. "fi_FI" for "language_country"
1354                 self.attributes = None
1355                 self.translatedAttributes = None
1356                 DreamInfoHandler.__init__(self, self.statusCallback, blocking = False, language = self.language)
1357                 self.directory = resolveFilename(SCOPE_METADIR)
1358                 if packagedata:
1359                         self.pluginname = packagedata[0]
1360                         self.details = packagedata[1]
1361                         self.pluginstate = packagedata[4]
1362                         self.statuspicinstance = packagedata[5]
1363                         self.divpicinstance = packagedata[6]
1364                         self.fillPackageDetails(self.details)
1365
1366                 self.thumbnail = ""
1367
1368                 self["shortcuts"] = ActionMap(["ShortcutActions", "WizardActions"],
1369                 {
1370                         "back": self.exit,
1371                         "red": self.exit,
1372                         "green": self.go,
1373                         "up": self.pageUp,
1374                         "down": self.pageDown,
1375                         "left": self.pageUp,
1376                         "right": self.pageDown,
1377                 }, -1)
1378
1379                 self["key_red"] = StaticText(_("Close"))
1380                 self["key_green"] = StaticText("")
1381                 self["author"] = StaticText()
1382                 self["statuspic"] = Pixmap()
1383                 self["divpic"] = Pixmap()
1384                 self["screenshot"] = Pixmap()
1385                 self["detailtext"] = ScrollLabel()
1386
1387                 self["statuspic"].hide()
1388                 self["screenshot"].hide()
1389                 self["divpic"].hide()
1390
1391                 self.package = self.packageDetails[0]
1392                 if self.package[0].has_key("attributes"):
1393                         self.attributes = self.package[0]["attributes"]
1394                 if self.package[0].has_key("translation"):
1395                         self.translatedAttributes = self.package[0]["translation"]
1396
1397                 self.cmdList = []
1398                 self.oktext = _("\nAfter pressing OK, please wait!")
1399                 self.picload = ePicLoad()
1400                 self.picload.PictureData.get().append(self.paintScreenshotPixmapCB)
1401                 self.onShown.append(self.setWindowTitle)
1402                 self.onLayoutFinish.append(self.setInfos)
1403
1404         def setWindowTitle(self):
1405                 self.setTitle(_("Package details for: " + self.pluginname))
1406
1407         def exit(self):
1408                 self.close(False)
1409
1410         def pageUp(self):
1411                 self["detailtext"].pageUp()
1412
1413         def pageDown(self):
1414                 self["detailtext"].pageDown()
1415
1416         def statusCallback(self, status, progress):
1417                 pass
1418
1419         def setInfos(self):
1420                 if self.translatedAttributes.has_key("name"):
1421                         self.pluginname = self.translatedAttributes["name"]
1422                 elif self.attributes.has_key("name"):
1423                         self.pluginname = self.attributes["name"]
1424                 else:
1425                         self.pluginname = _("unknown")
1426
1427                 if self.translatedAttributes.has_key("author"):
1428                         self.author = self.translatedAttributes["author"]
1429                 elif self.attributes.has_key("author"):
1430                         self.author = self.attributes["author"]
1431                 else:
1432                         self.author = _("unknown")
1433
1434                 if self.translatedAttributes.has_key("description"):
1435                         self.description = self.translatedAttributes["description"]
1436                 elif self.attributes.has_key("description"):
1437                         self.description = self.attributes["description"]
1438                 else:
1439                         self.description = _("No description available.")
1440
1441                 if self.translatedAttributes.has_key("screenshot"):
1442                         self.loadThumbnail(self.translatedAttributes)
1443                 else:
1444                         self.loadThumbnail(self.attributes)
1445
1446                 self["author"].setText(_("Author: ") + self.author)
1447                 self["detailtext"].setText(self.description.strip())
1448                 if self.pluginstate == 'installable':
1449                         self["key_green"].setText(_("Install"))
1450                 else:
1451                         self["key_green"].setText(_("Remove"))
1452
1453         def loadThumbnail(self, entry):
1454                 thumbnailUrl = None
1455                 if entry.has_key("screenshot"):
1456                         thumbnailUrl = entry["screenshot"]
1457                 if thumbnailUrl is not None:
1458                         self.thumbnail = "/tmp/" + thumbnailUrl.split('/')[-1]
1459                         print "[PluginDetails] downloading screenshot " + thumbnailUrl + " to " + self.thumbnail
1460                         client.downloadPage(thumbnailUrl,self.thumbnail).addCallback(self.setThumbnail).addErrback(self.fetchFailed)
1461                 else:
1462                         self.setThumbnail(noScreenshot = True)
1463
1464         def setThumbnail(self, noScreenshot = False):
1465                 if not noScreenshot:
1466                         filename = self.thumbnail
1467                 else:
1468                         filename = resolveFilename(SCOPE_CURRENT_PLUGIN, "SystemPlugins/SoftwareManager/noprev.png")
1469
1470                 sc = AVSwitch().getFramebufferScale()
1471                 self.picload.setPara((self["screenshot"].instance.size().width(), self["screenshot"].instance.size().height(), sc[0], sc[1], False, 1, "#00000000"))
1472                 self.picload.startDecode(filename)
1473
1474                 if self.statuspicinstance != None:
1475                         self["statuspic"].instance.setPixmap(self.statuspicinstance.__deref__())
1476                         self["statuspic"].show()
1477                 if self.divpicinstance != None:
1478                         self["divpic"].instance.setPixmap(self.divpicinstance.__deref__())
1479                         self["divpic"].show()
1480
1481         def paintScreenshotPixmapCB(self, picInfo=None):
1482                 ptr = self.picload.getData()
1483                 if ptr != None:
1484                         self["screenshot"].instance.setPixmap(ptr.__deref__())
1485                         self["screenshot"].show()
1486                 else:
1487                         self.setThumbnail(noScreenshot = True)
1488
1489         def go(self):
1490                 if self.attributes.has_key("package"):
1491                         self.packagefiles = self.attributes["package"]
1492                 self.cmdList = []
1493                 if self.pluginstate == 'installed':
1494                         if self.packagefiles:
1495                                 for package in self.packagefiles[:]:
1496                                         self.cmdList.append((IpkgComponent.CMD_REMOVE, { "package": package["name"] }))
1497                                         if len(self.cmdList):
1498                                                 self.session.openWithCallback(self.runRemove, MessageBox, _("Do you want to remove the package:\n") + self.pluginname + "\n" + self.oktext)
1499                 else:
1500                         if self.packagefiles:
1501                                 for package in self.packagefiles[:]:
1502                                         self.cmdList.append((IpkgComponent.CMD_INSTALL, { "package": package["name"] }))
1503                                         if len(self.cmdList):
1504                                                 self.session.openWithCallback(self.runUpgrade, MessageBox, _("Do you want to install the package:\n") + self.pluginname + "\n" + self.oktext)
1505
1506         def runUpgrade(self, result):
1507                 if result:
1508                         self.session.openWithCallback(self.runUpgradeFinished, Ipkg, cmdList = self.cmdList)
1509
1510         def runUpgradeFinished(self):
1511                 self.session.openWithCallback(self.UpgradeReboot, MessageBox, _("Installation finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
1512
1513         def UpgradeReboot(self, result):
1514                 if result is None:
1515                         return
1516                 if result is False:
1517                         self.close(True)
1518                 if result:
1519                         quitMainloop(3)
1520
1521         def runRemove(self, result):
1522                 if result:
1523                         self.session.openWithCallback(self.runRemoveFinished, Ipkg, cmdList = self.cmdList)
1524
1525         def runRemoveFinished(self):
1526                 self.session.openWithCallback(self.RemoveReboot, MessageBox, _("Remove finished.") +" "+_("Do you want to reboot your Dreambox?"), MessageBox.TYPE_YESNO)
1527
1528         def RemoveReboot(self, result):
1529                 if result is None:
1530                         return
1531                 if result is False:
1532                         self.close(True)
1533                 if result:
1534                         quitMainloop(3)
1535
1536         def reloadPluginlist(self):
1537                 plugins.readPluginList(resolveFilename(SCOPE_PLUGINS))
1538
1539         def fetchFailed(self,string):
1540                 self.setThumbnail(noScreenshot = True)
1541                 print "[PluginDetails] fetch failed " + string.getErrorMessage()
1542
1543
1544 class UpdatePlugin(Screen):
1545         skin = """
1546                 <screen name="UpdatePlugin" position="center,center" size="550,200" title="Software update" >
1547                         <widget name="activityslider" position="0,0" size="550,5"  />
1548                         <widget name="slider" position="0,150" size="550,30"  />
1549                         <widget source="package" render="Label" position="10,30" size="540,20" font="Regular;18" halign="center" valign="center" backgroundColor="#25062748" transparent="1" />
1550                         <widget source="status" render="Label" position="10,60" size="540,45" font="Regular;20" halign="center" valign="center" backgroundColor="#25062748" transparent="1" />
1551                 </screen>"""
1552
1553         def __init__(self, session, args = None):
1554                 Screen.__init__(self, session)
1555
1556                 self.sliderPackages = { "dreambox-dvb-modules": 1, "enigma2": 2, "tuxbox-image-info": 3 }
1557
1558                 self.slider = Slider(0, 4)
1559                 self["slider"] = self.slider
1560                 self.activityslider = Slider(0, 100)
1561                 self["activityslider"] = self.activityslider
1562                 self.status = StaticText(_("Upgrading Dreambox... Please wait"))
1563                 self["status"] = self.status
1564                 self.package = StaticText()
1565                 self["package"] = self.package
1566
1567                 self.packages = 0
1568                 self.error = 0
1569
1570                 self.activity = 0
1571                 self.activityTimer = eTimer()
1572                 self.activityTimer.callback.append(self.doActivityTimer)
1573                 self.activityTimer.start(100, False)
1574
1575                 self.ipkg = IpkgComponent()
1576                 self.ipkg.addCallback(self.ipkgCallback)
1577
1578                 self.updating = True
1579                 self.package.setText(_("Package list update"))
1580                 self.ipkg.startCmd(IpkgComponent.CMD_UPDATE)
1581
1582                 self["actions"] = ActionMap(["WizardActions"], 
1583                 {
1584                         "ok": self.exit,
1585                         "back": self.exit
1586                 }, -1)
1587
1588         def doActivityTimer(self):
1589                 self.activity += 1
1590                 if self.activity == 100:
1591                         self.activity = 0
1592                 self.activityslider.setValue(self.activity)
1593
1594         def ipkgCallback(self, event, param):
1595                 if event == IpkgComponent.EVENT_DOWNLOAD:
1596                         self.status.setText(_("Downloading"))
1597                 elif event == IpkgComponent.EVENT_UPGRADE:
1598                         if self.sliderPackages.has_key(param):
1599                                 self.slider.setValue(self.sliderPackages[param])
1600                         self.package.setText(param)
1601                         self.status.setText(_("Upgrading"))
1602                         self.packages += 1
1603                 elif event == IpkgComponent.EVENT_INSTALL:
1604                         self.package.setText(param)
1605                         self.status.setText(_("Installing"))
1606                         self.packages += 1
1607                 elif event == IpkgComponent.EVENT_CONFIGURING:
1608                         self.package.setText(param)
1609                         self.status.setText(_("Configuring"))
1610                 elif event == IpkgComponent.EVENT_MODIFIED:
1611                         self.session.openWithCallback(
1612                                 self.modificationCallback,
1613                                 MessageBox,
1614                                 _("A configuration file (%s) was modified since Installation.\nDo you want to keep your version?") % (param)
1615                         )
1616                 elif event == IpkgComponent.EVENT_ERROR:
1617                         self.error += 1
1618                 elif event == IpkgComponent.EVENT_DONE:
1619                         if self.updating:
1620                                 self.updating = False
1621                                 self.ipkg.startCmd(IpkgComponent.CMD_UPGRADE, args = {'test_only': False})
1622                         elif self.error == 0:
1623                                 self.slider.setValue(4)
1624                                 
1625                                 self.activityTimer.stop()
1626                                 self.activityslider.setValue(0)
1627                                 
1628                                 self.package.setText("")
1629                                 self.status.setText(_("Done - Installed or upgraded %d packages") % self.packages)
1630                         else:
1631                                 self.activityTimer.stop()
1632                                 self.activityslider.setValue(0)
1633                                 error = _("your dreambox might be unusable now. Please consult the manual for further assistance before rebooting your dreambox.")
1634                                 if self.packages == 0:
1635                                         error = _("No packages were upgraded yet. So you can check your network and try again.")
1636                                 if self.updating:
1637                                         error = _("Your dreambox isn't connected to the internet properly. Please check it and try again.")
1638                                 self.status.setText(_("Error") +  " - " + error)
1639                 #print event, "-", param
1640                 pass
1641
1642         def modificationCallback(self, res):
1643                 self.ipkg.write(res and "N" or "Y")
1644
1645         def exit(self):
1646                 if not self.ipkg.isRunning():
1647                         if self.packages != 0 and self.error == 0:
1648                                 self.session.openWithCallback(self.exitAnswer, MessageBox, _("Upgrade finished.") +" "+_("Do you want to reboot your Dreambox?"))
1649                         else:
1650                                 self.close()
1651
1652         def exitAnswer(self, result):
1653                 if result is not None and result:
1654                         quitMainloop(2)
1655                 self.close()
1656
1657
1658 class IpkgInstaller(Screen):
1659         skin = """
1660                 <screen name="IpkgInstaller" position="center,center" size="550,450" title="Install extensions" >
1661                         <ePixmap pixmap="skin_default/buttons/red.png" position="0,0" size="140,40" alphatest="on" />
1662                         <ePixmap pixmap="skin_default/buttons/green.png" position="140,0" size="140,40" alphatest="on" />
1663                         <widget source="key_red" render="Label" position="0,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#9f1313" transparent="1" />
1664                         <widget source="key_green" render="Label" position="140,0" zPosition="1" size="140,40" font="Regular;20" halign="center" valign="center" backgroundColor="#1f771f" transparent="1" />
1665                         <widget name="list" position="5,50" size="540,360" />
1666                         <ePixmap pixmap="skin_default/div-h.png" position="0,410" zPosition="10" size="560,2" transparent="1" alphatest="on" />
1667                         <widget source="introduction" render="Label" position="5,420" zPosition="10" size="550,30" halign="center" valign="center" font="Regular;22" transparent="1" shadowColor="black" shadowOffset="-1,-1" />
1668                 </screen>"""
1669         
1670         def __init__(self, session, list):
1671                 Screen.__init__(self, session)
1672
1673                 self.list = SelectionList()
1674                 self["list"] = self.list
1675                 for listindex in range(len(list)):
1676                         self.list.addSelection(list[listindex], list[listindex], listindex, True)
1677
1678                 self["key_red"] = StaticText(_("Close"))
1679                 self["key_green"] = StaticText(_("Install"))
1680                 self["introduction"] = StaticText(_("Press OK to toggle the selection."))
1681                 
1682                 self["actions"] = ActionMap(["OkCancelActions", "ColorActions"], 
1683                 {
1684                         "ok": self.list.toggleSelection, 
1685                         "cancel": self.close,
1686                         "red": self.close,
1687                         "green": self.install
1688                 }, -1)
1689
1690         def install(self):
1691                 list = self.list.getSelectionsList()
1692                 cmdList = []
1693                 for item in list:
1694                         cmdList.append((IpkgComponent.CMD_INSTALL, { "package": item[1] }))
1695                 self.session.open(Ipkg, cmdList = cmdList)
1696
1697
1698 def filescan_open(list, session, **kwargs):
1699         filelist = [x.path for x in list]
1700         session.open(IpkgInstaller, filelist) # list
1701
1702 def filescan(**kwargs):
1703         from Components.Scanner import Scanner, ScanPath
1704         return \
1705                 Scanner(mimetypes = ["application/x-debian-package"], 
1706                         paths_to_scan = 
1707                                 [
1708                                         ScanPath(path = "ipk", with_subdirs = True), 
1709                                         ScanPath(path = "", with_subdirs = False), 
1710                                 ], 
1711                         name = "Ipkg", 
1712                         description = _("Install extensions."),
1713                         openfnc = filescan_open, )
1714
1715
1716
1717 def UpgradeMain(session, **kwargs):
1718         session.open(UpdatePluginMenu)
1719
1720 def startSetup(menuid):
1721         if menuid != "setup": 
1722                 return [ ]
1723         return [(_("Software manager"), UpgradeMain, "software_manager", 50)]
1724
1725 def Plugins(path, **kwargs):
1726         global plugin_path
1727         plugin_path = path
1728         list = [
1729                 PluginDescriptor(name=_("Software manager"), description=_("Manage your receiver's software"), where = PluginDescriptor.WHERE_MENU, fnc=startSetup), 
1730                 PluginDescriptor(name=_("Ipkg"), where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan)
1731         ]
1732         if config.usage.setup_level.index >= 2: # expert+
1733                 list.append(PluginDescriptor(name=_("Software manager"), description=_("Manage your receiver's software"), where = PluginDescriptor.WHERE_EXTENSIONSMENU, fnc=UpgradeMain))
1734         return list