enhance usability of ZappingAlternatives plugin
[enigma2.git] / lib / python / Plugins / Extensions / ZappingAlternatives / plugin.py
1 from enigma import *
2 from Screens.Screen import Screen
3 from Screens.MessageBox import MessageBox
4 from Components.ActionMap import ActionMap
5 from Components.Label import Label
6 from Components.Input import Input
7 from Components.GUIComponent import *
8 from Components.Pixmap import Pixmap
9 from Components.MenuList import MenuList
10 from Components.FileList import FileEntryComponent, FileList
11 from Navigation import Navigation
12 import NavigationInstance
13 from Screens.ChannelSelection import SimpleChannelSelection
14 from ServiceReference import ServiceReference
15 from Plugins.Plugin import PluginDescriptor
16 from Tools.Directories import resolveFilename, SCOPE_CONFIG
17 import xml.dom.minidom
18 from Tools.XMLTools import elementsWithTag
19
20 import os
21
22 alternatives = {}
23
24 def addAlternative(service1, service2):
25         if not alternatives.has_key(service1):
26                 alternatives[service1] = []
27         alternatives[service1].append(service2)
28         if not alternatives.has_key(service2):
29                 alternatives[service2] = []
30         alternatives[service2].append(service1)
31
32 def removeAlternative(service1, service2):
33         alternatives[service1].remove(service2)
34         alternatives[service2].remove(service1)
35         if len(alternatives[service1]) == 0:
36                 del alternatives[service1]
37         if len(alternatives[service2]) == 0:
38                 del alternatives[service2]
39
40 def sortKey(x):
41         return str.lower(ServiceReference(x).getServiceName().strip())
42                         
43 class AlternativeZapping(Screen):
44         skin = """
45                 <screen position="100,100" size="560,400" title="Services alternatives setup..." >
46                         <widget name="red" position="0,0" size="140,40" backgroundColor="red" halign="center" valign="center" font="Regular;21" />
47                         <widget name="green" position="140,0" size="140,40" backgroundColor="green" halign="center" valign="center" font="Regular;21" />
48                         <widget name="yellow" position="280,0" size="140,40" backgroundColor="yellow" halign="center" valign="center" font="Regular;21" />
49                         <widget name="blue" position="420,0" size="140,40" backgroundColor="blue" halign="center" valign="center" font="Regular;21" />
50                         <widget name="serviceslist" position="0,40" size="280,360" />
51                         <widget name="alternativeslist" position="280,40" size="280,360" selectionDisabled="1" />
52                 </screen>"""
53         def __init__(self, session):
54                 self.skin = AlternativeZapping.skin
55                 Screen.__init__(self, session)
56
57                 self.filename = resolveFilename(SCOPE_CONFIG, "alternatives.xml")
58                 
59                 self.red = Label("")
60                 self["red"] = self.red
61                 self.green = Label(_("Add service"))
62                 self["green"] = self.green
63                 self.yellow = Label("")
64                 self["yellow"] = self.yellow
65                 self.blue = Label("")
66                 self["blue"] = self.blue
67                 
68                 self.alternatives = {}
69                 
70                 self.serviceslist = []
71                 self.alternativeslist = []
72                 
73                 try:
74                         self.loadAlternatives()
75                 except:
76                         pass
77                 self["serviceslist"] = MenuList(self.serviceslist)
78                 self["alternativeslist"] = MenuList(self.alternativeslist)
79
80                 self.onShown.append(self.updateServices)
81                 self.onShown.append(self.updateAlternatives)
82
83                 self["actions"] = ActionMap(["DirectionActions", "OkCancelActions", "ColorActions"],
84                 {
85                         "ok": self.go,
86                         "cancel": self.go,
87                         "up": self.up,
88                         "down": self.down,
89                         "left": self.left,
90                         "right": self.right,
91                         "red": self.redKey,
92                         "green": self.greenKey,
93                         "yellow": self.yellowKey,
94                         "blue": self.blueKey,
95                 }, -1)
96                 
97         def saveAlternatives(self):
98                 doc = xml.dom.minidom.Document()
99                 root_element = doc.createElement('alternatives')
100                 doc.appendChild(root_element)
101                 root_element.appendChild(doc.createTextNode("\n"))
102                 
103                 for alternative in self.alternatives.keys():
104                         t = doc.createTextNode("\t")
105                         root_element.appendChild(t)
106                         t = doc.createElement('service')
107                         t.setAttribute("ref", alternative)
108                         root_element.appendChild(t)
109                         t.appendChild(doc.createTextNode("\n"))
110                         for x in self.alternatives[alternative]:
111                                 t.appendChild(doc.createTextNode("\t\t"))
112                                 l = doc.createElement('alternative')
113                                 l.setAttribute("ref", str(x))
114                                 t.appendChild(l)
115                                 t.appendChild(doc.createTextNode("\n"))
116                         t.appendChild(doc.createTextNode("\t"))
117                         root_element.appendChild(t)
118                         t = doc.createTextNode("\n")
119                         root_element.appendChild(t)
120                 file = open(self.filename, "w")
121                 doc.writexml(file)
122                 file.write("\n")
123                 file.close()
124         
125         def loadAlternatives(self):
126                 self.alternatives = {}
127                 alternatives = {}
128                 doc = xml.dom.minidom.parse(self.filename)
129                 
130                 root = doc.childNodes[0]
131                 for service in elementsWithTag(root.childNodes, 'service'):
132                         newService = str(service.getAttribute('ref'))
133                         if not self.alternatives.has_key(newService):
134                                 self.alternatives[newService] = []
135                         for alternative in elementsWithTag(service.childNodes, 'alternative'):
136                                 newAlternative = str(alternative.getAttribute('ref'))
137                                 self.alternatives[newService].append(newAlternative)
138                                 addAlternative(newService, newAlternative)
139                 
140         def go(self):
141                 self.saveAlternatives()
142                 self.close()
143         
144         def up(self):
145                 self["serviceslist"].instance.moveSelection(self["serviceslist"].instance.moveUp)
146                 self.updateAlternatives()
147                 
148         def down(self):
149                 self["serviceslist"].instance.moveSelection(self["serviceslist"].instance.moveDown)
150                 self.updateAlternatives()
151         
152         def left(self):
153                 pass
154         
155         def right(self):
156                 pass
157         
158         def redKey(self):
159                 for x in self.alternatives[self["serviceslist"].getCurrent()[1]]:
160                         removeAlternative(self["serviceslist"].getCurrent()[1], x)
161                 if len(self.serviceslist) > 0:
162                         del self.alternatives[self["serviceslist"].getCurrent()[1]]
163                 self.updateServices()
164                 self.updateAlternatives()
165         
166         def finishedAlternativeSelection(self, args):
167                 self.alternatives[self["serviceslist"].getCurrent()[1]].append(str(ServiceReference(args)))
168                 addAlternative(self["serviceslist"].getCurrent()[1], str(ServiceReference(args)))
169                 self.updateAlternatives()
170         
171         def updateServices(self):
172                 self.serviceslist = []
173                 keys = self.alternatives.keys()
174                 keys.sort(key = sortKey)
175                 for x in keys:
176                         self.serviceslist.append((ServiceReference(x).getServiceName(), x))
177                         
178                 self["serviceslist"].setList(self.serviceslist)
179                 if len(self.serviceslist) > 0:
180                         self.yellow.setText(_("Add alternative"))
181                         self.red.setText(_("Remove service"))
182                 else:
183                         self.yellow.setText("")
184                         self.red.setText("")
185         
186         def selectService(self, ref):
187                 count = 0
188                 for x in self["serviceslist"].list:
189                         if x[1] == ref:
190                                 self["serviceslist"].instance.moveSelectionTo(count)
191                                 return
192                         count += 1
193                         
194                         
195         def updateAlternatives(self):
196                 self.alternativeslist = []
197         
198                 if len(self.serviceslist) > 0:
199                         alternativelist = self.alternatives[self["serviceslist"].getCurrent()[1]]
200
201                         for x in alternativelist:
202                                 self.alternativeslist.append((ServiceReference(x).getServiceName(), x))
203                         
204                 self["alternativeslist"].setList(self.alternativeslist)
205                         
206         def greenKey(self):
207                 self.session.openWithCallback(self.finishedChannelSelection, SimpleChannelSelection, _("Select reference service"))
208
209         def finishedChannelSelection(self, args):
210                 serviceString = str(ServiceReference(args))
211                 if not self.alternatives.has_key(serviceString):
212                         self.alternatives[serviceString] = []
213                 self.updateServices()
214                 self.updateAlternatives()
215                 self.selectService(serviceString)
216
217         def yellowKey(self):
218                 if len(self.serviceslist) > 0:
219                         self.session.openWithCallback(self.finishedAlternativeSelection, SimpleChannelSelection, _("Select alternative service"))
220         
221         def blueKey(self):
222                 pass
223
224
225 oldPlayService = NavigationInstance.instance.playService
226
227 def playService(self, ref):
228         if not oldPlayService(ref):
229                 if alternatives.has_key(str(ServiceReference(ref))):
230                         for x in alternatives[str(ServiceReference(ref))]:
231                                 if oldPlayService(ServiceReference(x).ref):
232                                         return 1
233                 return 0
234         return 1
235
236 def autostart(reason):
237         if reason == 0:
238                 NavigationInstance.instance.playService = type(NavigationInstance.instance.playService)(playService, NavigationInstance, Navigation)
239
240 def AlternativeZappingSetup(session):
241         session.open(AlternativeZapping)
242
243 def Plugins():
244         return [PluginDescriptor(where = PluginDescriptor.WHERE_AUTOSTART, fnc = autostart),
245                         PluginDescriptor(name="Alternative services setup" , description="Defines alternatives for services.", where = PluginDescriptor.WHERE_PLUGINMENU, fnc=AlternativeZappingSetup)]