1 # for localized messages
4 from enigma import eEPGCache, eServiceReference, RT_HALIGN_LEFT, \
5 RT_HALIGN_RIGHT, eListboxPythonMultiContent
7 from Tools.LoadPixmap import LoadPixmap
8 from ServiceReference import ServiceReference
10 from Screens.ChannelSelection import SimpleChannelSelection
11 from Screens.ChoiceBox import ChoiceBox
12 from Screens.EpgSelection import EPGSelection
13 from Screens.MessageBox import MessageBox
14 from Screens.Screen import Screen
15 from NTIVirtualKeyBoard import NTIVirtualKeyBoard
17 from Components.ActionMap import ActionMap
18 from Components.Button import Button
19 from Components.config import config
20 from Components.EpgList import EPGList, EPG_TYPE_SINGLE, EPG_TYPE_MULTI
21 from Components.TimerList import TimerList
22 from Components.Sources.ServiceEvent import ServiceEvent
23 from Components.Sources.Event import Event
25 from time import localtime
27 # Partnerbox installed and icons in epglist enabled?
29 from Plugins.Extensions.Partnerbox.PartnerboxEPGList import \
30 isInRemoteTimer, getRemoteClockPixmap
31 from Plugins.Extensions.Partnerbox.PartnerboxSetup import \
32 showPartnerboxIconsinEPGList
33 PartnerBoxIconsEnabled = showPartnerboxIconsinEPGList()
35 PartnerBoxIconsEnabled = False
37 # AutoTimer installed?
39 from Plugins.Extensions.AutoTimer.AutoTimerEditor import \
40 addAutotimerFromEvent, addAutotimerFromSearchString
41 autoTimerAvailable = True
43 autoTimerAvailable = False
45 # Overwrite EPGSelection.__init__ with our modified one
46 baseEPGSelection__init__ = None
47 def EPGSelectionInit():
48 global baseEPGSelection__init__
49 if baseEPGSelection__init__ is None:
50 baseEPGSelection__init__ = EPGSelection.__init__
51 EPGSelection.__init__ = EPGSelection__init__
53 # Modified EPGSelection __init__
54 def EPGSelection__init__(self, session, service, zapFunc=None, eventid=None, bouquetChangeCB=None, serviceChangeCB=None):
55 baseEPGSelection__init__(self, session, service, zapFunc, eventid, bouquetChangeCB, serviceChangeCB)
56 if self.type != EPG_TYPE_MULTI:
58 cur = self["list"].getCurrent()
59 if cur[0] is not None:
60 name = cur[0].getEventName()
63 self.session.open(EPGSearch, name, False)
65 self["epgsearch_actions"] = ActionMap(["EPGSelectActions"],
69 self["key_blue"].text = _("EPG Search")
71 # Modified EPGSearchList with support for PartnerBox
72 class EPGSearchList(EPGList):
73 def __init__(self, type=EPG_TYPE_SINGLE, selChangedCB=None, timer=None):
74 EPGList.__init__(self, type, selChangedCB, timer)
75 self.l.setBuildFunc(self.buildEPGSearchEntry)
77 if PartnerBoxIconsEnabled:
78 # Partnerbox Clock Icons
79 self.remote_clock_pixmap = LoadPixmap('/usr/lib/enigma2/python/Plugins/Extensions/Partnerbox/icons/remote_epgclock.png')
80 self.remote_clock_add_pixmap = LoadPixmap('/usr/lib/enigma2/python/Plugins/Extensions/Partnerbox/icons/remote_epgclock_add.png')
81 self.remote_clock_pre_pixmap = LoadPixmap('/usr/lib/enigma2/python/Plugins/Extensions/Partnerbox/icons/remote_epgclock_pre.png')
82 self.remote_clock_post_pixmap = LoadPixmap('/usr/lib/enigma2/python/Plugins/Extensions/Partnerbox/icons/remote_epgclock_post.png')
83 self.remote_clock_prepost_pixmap = LoadPixmap('/usr/lib/enigma2/python/Plugins/Extensions/Partnerbox/icons/remote_epgclock_prepost.png')
85 def buildEPGSearchEntry(self, service, eventId, beginTime, duration, EventName):
86 rec1 = beginTime and self.timer.isInTimer(eventId, beginTime, duration, service)
88 if PartnerBoxIconsEnabled:
89 rec2 = beginTime and isInRemoteTimer(self,beginTime, duration, service)
92 r1 = self.weekday_rect
93 r2 = self.datetime_rect
95 t = localtime(beginTime)
96 serviceref = ServiceReference(service) # for Servicename
98 None, # no private data needed
99 (eListboxPythonMultiContent.TYPE_TEXT, r1.left(), r1.top(), r1.width(), r1.height(), 0, RT_HALIGN_RIGHT, self.days[t[6]]),
100 (eListboxPythonMultiContent.TYPE_TEXT, r2.left(), r2.top(), r2.width(), r1.height(), 0, RT_HALIGN_RIGHT, "%02d.%02d, %02d:%02d"%(t[2],t[1],t[3],t[4]))
104 clock_pic = self.getClockPixmap(service, beginTime, duration, eventId)
105 # maybe Partnerbox too
107 clock_pic_partnerbox = getRemoteClockPixmap(self,service, beginTime, duration, eventId)
109 clock_pic = getRemoteClockPixmap(self,service, beginTime, duration, eventId)
111 # Partnerbox and local
113 (eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, r3.left(), r3.top(), 21, 21, clock_pic),
114 (eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, r3.left() + 25, r3.top(), 21, 21, clock_pic_partnerbox),
115 (eListboxPythonMultiContent.TYPE_TEXT, r3.left() + 50, r3.top(), r3.width(), r3.height(), 0, RT_HALIGN_LEFT, serviceref.getServiceName() + ": " + EventName)))
118 (eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, r3.left(), r3.top(), 21, 21, clock_pic),
119 (eListboxPythonMultiContent.TYPE_TEXT, r3.left() + 25, r3.top(), r3.width(), r3.height(), 0, RT_HALIGN_LEFT, serviceref.getServiceName() + ": " + EventName)))
121 res.append((eListboxPythonMultiContent.TYPE_TEXT, r3.left(), r3.top(), r3.width(), r3.height(), 0, RT_HALIGN_LEFT, serviceref.getServiceName() + ": " + EventName))
124 # main class of plugin
125 class EPGSearch(EPGSelection):
126 def __init__(self, session, *args):
127 Screen.__init__(self, session)
128 self.skinName = ["EPGSearch", "EPGSelection"]
130 self.searchargs = args
133 # XXX: we lose sort begin/end here
134 self["key_yellow"] = Button(_("New Search"))
135 self["key_blue"] = Button(_("History"))
137 # begin stripped copy of EPGSelection.__init__
138 self.bouquetChangeCB = None
139 self.serviceChangeCB = None
140 self.ask_time = -1 #now
141 self["key_red"] = Button("")
142 self.closeRecursive = False
143 self.saved_title = None
144 self["Service"] = ServiceEvent()
145 self["Event"] = Event()
146 self.type = EPG_TYPE_SINGLE
147 self.currentService=None
150 self["key_green"] = Button(_("Add timer"))
151 self.key_green_choice = self.ADD_TIMER
152 self.key_red_choice = self.EMPTY
153 self["list"] = EPGSearchList(type = self.type, selChangedCB = self.onSelectionChanged, timer = session.nav.RecordTimer)
154 self["actions"] = ActionMap(["EPGSelectActions", "OkCancelActions", "MenuActions"],
157 "cancel": self.closeScreen,
158 "ok": self.eventSelected,
159 "timerAdd": self.timerAdd,
160 "yellow": self.yellowButtonPressed,
161 "blue": self.blueButtonPressed,
162 "info": self.infoKeyPressed,
163 "red": self.zapTo, # needed --> Partnerbox
164 "nextBouquet": self.nextBouquet, # just used in multi epg yet
165 "prevBouquet": self.prevBouquet, # just used in multi epg yet
166 "nextService": self.nextService, # just used in single epg yet
167 "prevService": self.prevService, # just used in single epg yet
170 self["actions"].csel = self
171 self.onLayoutFinish.append(self.onCreate)
172 # end stripped copy of EPGSelection.__init__
175 if PartnerBoxIconsEnabled:
176 EPGSelection.PartnerboxInit(self, False)
179 self.setTitle(_("EPG Search"))
182 self.searchEPG(*self.searchargs)
191 if PartnerBoxIconsEnabled:
192 EPGSelection.GetPartnerboxTimerlist(self)
194 def closeScreen(self):
196 config.plugins.epgsearch.save()
197 EPGSelection.closeScreen(self)
199 def yellowButtonPressed(self):
200 self.session.openWithCallback(
203 title = _("Enter text to search for")
208 (_("Import from Timer"), self.importFromTimer),
209 (_("Import from EPG"), self.importFromEPG),
212 if autoTimerAvailable:
214 (_("Import from AutoTimer"), self.importFromAutoTimer),
215 (_("Save search as AutoTimer"), self.addAutoTimer),
216 (_("Export selected as AutoTimer"), self.exportAutoTimer),
219 self.session.openWithCallback(
225 def menuCallback(self, ret):
228 def importFromTimer(self):
229 self.session.openWithCallback(
234 def importFromEPG(self):
235 self.session.openWithCallback(
237 EPGSearchChannelSelection
240 def importFromAutoTimer(self):
241 removeInstance = False
244 from Plugins.Extensions.AutoTimer.plugin import autotimer
246 if autotimer is None:
247 removeInstance = True
249 from Plugins.Extensions.AutoTimer.AutoTimer import AutoTimer
250 autotimer = AutoTimer()
252 # Read in configuration
257 _("Could not read AutoTimer timer list: %s") % e,
258 type = MessageBox.TYPE_ERROR
261 # Fetch match strings
262 # XXX: we could use the timer title as description
263 options = [(x.match, x.match) for x in autotimer.getTimerList()]
265 self.session.openWithCallback(
266 self.searchEPGWrapper,
268 title = _("Select text to search for"),
272 # Remove instance if there wasn't one before
276 def addAutoTimer(self):
277 addAutotimerFromSearchString(self.session, self.currSearch)
279 def exportAutoTimer(self):
280 cur = self['list'].getCurrent()
283 addAutotimerFromEvent(self.session, cur[0], cur[1])
285 def blueButtonPressed(self):
286 options = [(x, x) for x in config.plugins.epgsearch.history.value]
289 self.session.openWithCallback(
290 self.searchEPGWrapper,
292 title = _("Select text to search for"),
299 type = MessageBox.TYPE_INFO
302 def searchEPGWrapper(self, ret):
304 self.searchEPG(ret[1])
306 def searchEPG(self, searchString = None, searchSave = True):
308 self.currSearch = searchString
311 history = config.plugins.epgsearch.history.value
312 if searchString not in history:
313 history.insert(0, searchString)
314 if len(history) > 10:
317 history.remove(searchString)
318 history.insert(0, searchString)
320 # Workaround to allow search for umlauts if we know the encoding (pretty bad, I know...)
321 encoding = config.plugins.epgsearch.encoding.value
322 if encoding != 'UTF-8':
324 searchString = searchString.decode('UTF-8', 'replace').encode(encoding, 'replace')
325 except (UnicodeDecodeError, UnicodeEncodeError):
328 # Search EPG, default to empty list
329 epgcache = eEPGCache.getInstance() # XXX: the EPGList also keeps an instance of the cache but we better make sure that we get what we want :-)
330 ret = epgcache.search(('RIBDT', 200, eEPGCache.PARTIAL_TITLE_SEARCH, searchString, eEPGCache.NO_CASE_CHECK)) or []
331 ret.sort(key = lambda x: x[2]) # sort by time
339 class EPGSearchTimerImport(Screen):
340 def __init__(self, session):
341 Screen.__init__(self, session)
342 self.skinName = ["EPGSearchTimerImport", "TimerEditList"]
347 self["timerlist"] = TimerList(self.list)
349 self["key_red"] = Button(_("Cancel"))
350 self["key_green"] = Button(_("OK"))
351 self["key_yellow"] = Button("")
352 self["key_blue"] = Button("")
354 self["actions"] = ActionMap(["OkCancelActions", "ColorActions"],
357 "cancel": self.cancel,
358 "green": self.search,
361 self.onLayoutFinish.append(self.setCustomTitle)
363 def setCustomTitle(self):
364 self.setTitle(_("Select a timer to search"))
366 def fillTimerList(self):
370 for timer in self.session.nav.RecordTimer.timer_list:
371 l.append((timer, False))
373 for timer in self.session.nav.RecordTimer.processed_timers:
374 l.append((timer, True))
375 l.sort(key = lambda x: x[0].begin)
378 cur = self["timerlist"].getCurrent()
385 class EPGSearchChannelSelection(SimpleChannelSelection):
386 def __init__(self, session):
387 SimpleChannelSelection.__init__(self, session, _("Channel Selection"))
388 self.skinName = ["EPGSearchChannelSelection", "SimpleChannelSelection"]
390 self["ChannelSelectEPGActions"] = ActionMap(["ChannelSelectEPGActions"],
392 "showEPGList": self.channelSelected
395 def channelSelected(self):
396 ref = self.getCurrentSelection()
397 if (ref.flags & 7) == 7:
399 elif not (ref.flags & eServiceReference.isMarker):
400 self.session.openWithCallback(
402 EPGSearchEPGSelection,
407 def epgClosed(self, ret = None):
411 class EPGSearchEPGSelection(EPGSelection):
412 def __init__(self, session, ref, openPlugin):
413 EPGSelection.__init__(self, session, ref)
414 self.skinName = ["EPGSearchEPGSelection", "EPGSelection"]
415 self["key_green"].text = _("Search")
416 self.openPlugin = openPlugin
418 def infoKeyPressed(self):
422 cur = self["list"].getCurrent()
434 self.close(evt.getEventName())