change eventinfo hook: allow to search for different than currently running event...
[enigma2-plugins.git] / epgsearch / src / EPGSearch.py
1 # for localized messages
2 from . import _
3
4 from enigma import eEPGCache, eServiceReference
5
6 from Screens.ChannelSelection import SimpleChannelSelection
7 from Screens.ChoiceBox import ChoiceBox
8 from Screens.EpgSelection import EPGSelection
9 from Screens.InputBox import InputBox
10 from Screens.MessageBox import MessageBox
11 from Screens.Screen import Screen
12
13 from Components.ActionMap import ActionMap
14 from Components.Button import Button
15 from Components.config import config
16 from Components.TimerList import TimerList
17
18 class EPGSearch(EPGSelection):
19         def __init__(self, session, *args):
20                 EPGSelection.__init__(self, session, '') # Empty string serviceref so we get EPG_TYPE_SINGLE
21                 self.skinName = "EPGSelection"
22
23                 self["MenuActions"] = ActionMap(["MenuActions"],
24                 {
25                                 "menu": self.menu,
26                 })
27
28                 # XXX: we lose sort begin/end here
29                 self["key_yellow"].setText(_("New Search"))
30                 self["key_blue"].setText(_("History"))
31
32                 self.searchargs = args
33
34         def onCreate(self):
35                 if self.searchargs:
36                         self.searchEPG(*self.searchargs)
37                 else:
38                         l = self["list"]
39                         l.recalcEntrySize()
40                         l.list = []
41                         l.l.setList(l.list)
42                 del self.searchargs
43
44         def closeScreen(self):
45                 # Save our history
46                 config.plugins.epgsearch.save()
47                 EPGSelection.closeScreen(self)
48
49         def yellowButtonPressed(self):
50                 self.session.openWithCallback(
51                         self.searchEPG,
52                         InputBox,
53                         title = _("Enter text to search for")
54                 )
55
56         def menu(self):
57                 options = (
58                         (_("Import from Timer"), "importFromTimer"),
59                         (_("Import from EPG"), "importFromEPG")
60                 )
61
62                 self.session.openWithCallback(
63                         self.menuCallback,
64                         ChoiceBox,
65                         list = options
66                 )
67
68         def menuCallback(self, ret):
69                 if ret:
70                         ret = ret[1]
71                         if ret is "importFromTimer":
72                                 self.session.openWithCallback(
73                                         self.searchEPG,
74                                         EPGSearchTimerImport
75                                 )
76                         elif ret is "importFromEPG":
77                                 self.session.openWithCallback(
78                                         self.searchEPG,
79                                         EPGSearchChannelSelection
80                                 )
81
82         def blueButtonPressed(self):
83                 options = [(x, x) for x in config.plugins.epgsearch.history.value]
84
85                 if options:
86                         self.session.openWithCallback(
87                                 self.searchEPGWrapper,
88                                 ChoiceBox,
89                                 title = _("Select text to search for"),
90                                 list = options
91                         )
92                 else:
93                         self.session.open(
94                                 MessageBox,
95                                 _("No history"),
96                                 type = MessageBox.TYPE_INFO
97                         )
98
99         def searchEPGWrapper(self, ret):
100                 if ret:
101                         self.searchEPG(ret[1])
102
103         def searchEPG(self, searchString = None, searchSave = True):
104                 if searchString:
105                         if searchSave:
106                                 # Maintain history
107                                 history = config.plugins.epgsearch.history.value
108                                 if searchString not in history:
109                                         history.insert(0, searchString)
110                                         if len(history) > 10:
111                                                 history.pop(10)
112                                 else:
113                                         history.remove(searchString)
114                                         history.insert(0, searchString)
115
116                         # Workaround to allow search for umlauts if we know the encoding (pretty bad, I know...)
117                         encoding = config.plugins.epgsearch.encoding.value
118                         if encoding != 'UTF-8':
119                                 try:
120                                         searchString = searchString.decode('UTF-8', 'replace').encode(encoding)
121                                 except UnicodeDecodeError:
122                                         pass
123
124                         # Search EPG, default to empty list
125                         epgcache = eEPGCache.getInstance() # XXX: the EPGList also keeps an instance of the cache but we better make sure that we get what we want :-)
126                         ret = epgcache.search(('RIBDT', 200, eEPGCache.PARTIAL_TITLE_SEARCH, searchString, eEPGCache.NO_CASE_CHECK)) or []
127                         ret.sort(key = lambda x: x[2]) # sort by time
128
129                         # Update List
130                         l = self["list"]
131                         l.recalcEntrySize()
132                         l.list = ret
133                         l.l.setList(ret)
134
135 class EPGSearchTimerImport(Screen):
136         def __init__(self, session):
137                 Screen.__init__(self, session)
138                 self.skinName = "TimerEditList"
139
140                 self.list = []
141                 self.fillTimerList()
142
143                 self["timerlist"] = TimerList(self.list)
144
145                 self["key_red"] = Button(_("Cancel"))
146                 self["key_green"] = Button(_("OK"))
147                 self["key_yellow"] = Button("")
148                 self["key_blue"] = Button("")
149
150                 self["actions"] = ActionMap(["OkCancelActions", "ColorActions"],
151                 {
152                         "ok": self.search,
153                         "cancel": self.cancel,
154                         "green": self.search,
155                         "red": self.cancel
156                 }, -1)
157                 self.onLayoutFinish.append(self.setCustomTitle)
158
159         def setCustomTitle(self):
160                 self.setTitle(_("Select a timer to search"))
161
162         def fillTimerList(self):
163                 l = self.list
164                 del l[:]
165
166                 for timer in self.session.nav.RecordTimer.timer_list:
167                         l.append((timer, False))
168
169                 for timer in self.session.nav.RecordTimer.processed_timers:
170                         l.append((timer, True))
171                 l.sort(key = lambda x: x[0].begin)
172
173         def search(self):
174                 cur = self["timerlist"].getCurrent()
175                 if cur:
176                         self.close(cur.name)
177
178         def cancel(self):
179                 self.close(None)
180
181 class EPGSearchChannelSelection(SimpleChannelSelection):
182         def __init__(self, session):
183                 SimpleChannelSelection.__init__(self, session, _("Channel Selection"))
184                 self.skinName = "SimpleChannelSelection"
185
186                 self["ChannelSelectEPGActions"] = ActionMap(["ChannelSelectEPGActions"],
187                 {
188                                 "showEPGList": self.channelSelected
189                 })
190
191         def channelSelected(self):
192                 ref = self.getCurrentSelection()
193                 if (ref.flags & 7) == 7:
194                         self.enterPath(ref)
195                 elif not (ref.flags & eServiceReference.isMarker):
196                         self.session.openWithCallback(
197                                 self.epgClosed,
198                                 EPGSearchEPGSelection,
199                                 ref,
200                                 False
201                         )
202
203         def epgClosed(self, ret = None):
204                 if ret:
205                         self.close(ret)
206
207 class EPGSearchEPGSelection(EPGSelection):
208         def __init__(self, session, ref, openPlugin):
209                 EPGSelection.__init__(self, session, ref)
210                 self.skinName = "EPGSelection"
211                 self["key_green"].setText(_("Search"))
212                 self.openPlugin = openPlugin
213
214         def infoKeyPressed(self):
215                 self.timerAdd()
216
217         def timerAdd(self):
218                 cur = self["list"].getCurrent()
219                 evt = cur[0]
220                 sref = cur[1]
221                 if not evt:
222                         return
223
224                 if self.openPlugin:
225                         self.session.open(
226                                 EPGSearch,
227                                 evt.getEventName()
228                         )
229                 else:
230                         self.close(evt.getEventName())
231