open editor after importing with addAutotimerFrom*
[vuplus_dvbapp-plugin] / autotimer / src / AutoTimerEditor.py
1 # GUI (Screens)
2 from Screens.Screen import Screen
3 from Components.ConfigList import ConfigListScreen
4 from Screens.ChannelSelection import SimpleChannelSelection
5 from Screens.MessageBox import MessageBox
6 from Screens.ChoiceBox import ChoiceBox
7
8 # GUI (Summary)
9 from Screens.Setup import SetupSummary
10
11 # GUI (Components)
12 from Components.ActionMap import ActionMap
13 from Components.Button import Button
14
15 # Configuration
16 from Components.config import getConfigListEntry, ConfigEnableDisable, \
17         ConfigYesNo, ConfigText, ConfigClock, ConfigNumber, ConfigSelection, \
18         config
19
20 # Timer
21 from RecordTimer import AFTEREVENT
22
23 # Needed to convert our timestamp back and forth
24 from time import localtime, mktime
25
26 # Show ServiceName instead of ServiceReference
27 from ServiceReference import ServiceReference
28
29 # addAutotimerFromService
30 from enigma import eServiceCenter, iServiceInformation
31
32 weekdays = [
33         ("0", _("Monday")),
34         ("1", _("Tuesday")),
35         ("2", _("Wednesday")),
36         ("3", _("Thursday")),
37         ("4", _("Friday")),
38         ("5", _("Saturday")),
39         ("6", _("Sunday")),
40         ("weekend", _("Weekend")),
41         ("weekday", _("Weekday"))
42 ]
43
44 class SimpleBouquetSelection(SimpleChannelSelection):
45         def __init__(self, session, title):
46                 SimpleChannelSelection.__init__(self, session, title)
47                 self.skinName = "SimpleChannelSelection"
48
49         def channelSelected(self): # just return selected service
50                 ref = self.getCurrentSelection()
51                 if (ref.flags & 7) == 7:
52                         self.close(ref)
53                 else:
54                         # We return the currently active path here
55                         # Asking the user if this is what he wants might be better though
56                         self.close(self.servicePath[-1])
57
58 class AutoTimerEditor(Screen, ConfigListScreen):
59         """Edit AutoTimer"""
60
61         skin = """<screen name="AutoTimerEdit" title="Edit AutoTimer" position="75,155" size="565,280">
62                 <widget name="config" position="5,5" size="555,225" scrollbarMode="showOnDemand" />
63                 <ePixmap position="0,235" zPosition="4" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
64                 <ePixmap position="140,235" zPosition="4" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
65                 <ePixmap position="280,235" zPosition="4" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
66                 <ePixmap position="420,235" zPosition="4" size="140,40" pixmap="skin_default/buttons/blue.png" transparent="1" alphatest="on" />
67                 <widget name="key_red" position="0,235" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
68                 <widget name="key_green" position="140,235" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
69                 <widget name="key_yellow" position="280,235" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
70                 <widget name="key_blue" position="420,235" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
71         </screen>"""
72
73         def __init__(self, session, timer):
74                 Screen.__init__(self, session)
75
76                 # Keep Timer
77                 self.timer = timer
78
79                 # Summary
80                 self.setup_title = "AutoTimer Editor"
81                 self.onChangedEntry = []
82
83                 # See if we are filtering some strings
84                 self.excludes = (
85                         timer.getExcludedTitle(),
86                         timer.getExcludedShort(),
87                         timer.getExcludedDescription(),
88                         timer.getExcludedDays()
89                 )
90                 self.includes = (
91                         timer.getIncludedTitle(),
92                         timer.getIncludedShort(),
93                         timer.getIncludedDescription(),
94                         timer.getIncludedDays()
95                 )
96                 if len(self.excludes[0]) or len(self.excludes[1]) \
97                                 or len(self.excludes[2]) or len(self.excludes[3]) \
98                                 or len(self.includes[0]) or len(self.includes[1]) \
99                                 or len(self.includes[2]) or len(self.includes[3]):
100                         self.filterSet = True
101                 else:
102                         self.filterSet = False
103
104                 # See if services are restricted
105                 self.services = timer.getServices()
106                 self.bouquets = timer.getBouquets()
107                 if len(self.services) or len(self.bouquets):
108                         self.serviceRestriction = True
109                 else:
110                         self.serviceRestriction = False
111
112                 self.createSetup(timer)
113
114                 # We might need to change shown items, so add some notifiers
115                 self.timespan.addNotifier(self.reloadList, initial_call = False)
116                 self.offset.addNotifier(self.reloadList, initial_call = False)
117                 self.duration.addNotifier(self.reloadList, initial_call = False)
118                 self.afterevent.addNotifier(self.reloadList, initial_call = False)
119                 self.afterevent_timespan.addNotifier(self.reloadList, initial_call = False)
120                 self.counter.addNotifier(self.reloadList, initial_call = False)
121
122                 self.refresh()
123
124                 ConfigListScreen.__init__(self, self.list, session = session, on_change = self.changed)
125
126                 # Initialize Buttons
127                 self["key_red"] = Button(_("Cancel"))
128                 self["key_green"] = Button(_("OK"))
129                 self["key_yellow"] = Button()
130                 self["key_blue"] = Button()
131
132                 # Set Button texts
133                 self.renameServiceButton()
134                 self.renameFilterButton()
135
136                 # Define Actions
137                 self["actions"] = ActionMap(["SetupActions", "ColorActions"],
138                         {
139                                 "cancel": self.cancel,
140                                 "save": self.maybeSave,
141                                 "ok": self.ok,
142                                 "yellow": self.editFilter,
143                                 "blue": self.editServices
144                         }, -2
145                 )
146
147                 # Trigger change
148                 self.changed()
149
150         def renameFilterButton(self):
151                 if self.filterSet:
152                         self["key_yellow"].setText(_("Edit Filters"))
153                 else:
154                         self["key_yellow"].setText(_("Add Filters"))
155
156         def renameServiceButton(self):
157                 if self.serviceRestriction:
158                         self["key_blue"].setText(_("Edit Services"))
159                 else:
160                         self["key_blue"].setText(_("Add Services"))
161
162         def changed(self):
163                 for x in self.onChangedEntry:
164                         try:
165                                 x()
166                         except:
167                                 pass
168
169         def getCurrentEntry(self):
170                 return self["config"].getCurrent()[0]
171
172         def getCurrentValue(self):
173                 return str(self["config"].getCurrent()[1].getText())
174
175         def createSummary(self):
176                 return SetupSummary
177
178         def createSetup(self, timer):
179                 # Name
180                 self.name = ConfigText(default = timer.name, fixed_size = False)
181
182                 # Match
183                 self.match = ConfigText(default = timer.match, fixed_size = False)
184                 self.match.setUseableChars('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789') # XXX: what exactly is useable? :-)
185
186                 # Justplay
187                 self.justplay = ConfigSelection(choices = [("zap", _("zap")), ("record", _("record"))], default = {0: "record", 1: "zap"}[int(timer.justplay)])
188
189                 # Timespan
190                 now = [x for x in localtime()]
191                 if timer.hasTimespan():
192                         default = True
193                         now[3] = timer.timespan[0][0]
194                         now[4] = timer.timespan[0][1]
195                         begin = mktime(now)
196                         now[3] = timer.timespan[1][0]
197                         now[4] = timer.timespan[1][1]
198                         end = mktime(now)
199                 else:
200                         default = False
201                         now[3] = 20
202                         now[4] = 15
203                         begin = mktime(now)
204                         now[3] = 23
205                         now[4] = 15
206                         end = mktime(now)
207                 self.timespan = ConfigEnableDisable(default = default)
208                 self.timespanbegin = ConfigClock(default = begin)
209                 self.timespanend = ConfigClock(default = end)
210
211                 # Services have their own Screen
212
213                 # Offset
214                 if timer.hasOffset():
215                         default = True
216                         begin = timer.getOffsetBegin()
217                         end = timer.getOffsetEnd()
218                 else:
219                         default = False
220                         begin = 5
221                         end = 5
222                 self.offset = ConfigEnableDisable(default = default)
223                 self.offsetbegin = ConfigNumber(default = begin)
224                 self.offsetend = ConfigNumber(default = end)
225
226                 # AfterEvent
227                 if timer.hasAfterEvent():
228                         afterevent = { None: "default", AFTEREVENT.NONE: "nothing", AFTEREVENT.DEEPSTANDBY: "deepstandby", AFTEREVENT.STANDBY: "standby"}[timer.afterevent[0][0]]
229                 else:
230                         afterevent = "default"
231                 self.afterevent = ConfigSelection(choices = [("default", _("standard")), ("nothing", _("do nothing")), ("standby", _("go to standby")), ("deepstandby", _("go to deep standby"))], default = afterevent)
232
233                 # AfterEvent (Timespan)
234                 if timer.hasAfterEvent() and timer.afterevent[0][1][0] is not None:
235                         default = True
236                         now[3] = timer.afterevent[0][1][0][0]
237                         now[4] = timer.afterevent[0][1][0][1]
238                         begin = mktime(now)
239                         now[3] = timer.afterevent[0][1][1][0]
240                         now[4] = timer.afterevent[0][1][1][1]
241                         end = mktime(now)
242                 else:
243                         default = False
244                         now[3] = 23
245                         now[4] = 15
246                         begin = mktime(now)
247                         now[3] = 7
248                         now[4] = 0
249                         end = mktime(now)
250                 self.afterevent_timespan = ConfigEnableDisable(default = default)
251                 self.afterevent_timespanbegin = ConfigClock(default = begin)
252                 self.afterevent_timespanend = ConfigClock(default = end)
253
254                 # Enabled
255                 self.enabled = ConfigYesNo(default = timer.enabled)
256
257                 # Maxduration
258                 if timer.hasDuration():
259                         default = True
260                         duration = timer.getDuration()
261                 else:
262                         default = False
263                         duration =70
264                 self.duration = ConfigEnableDisable(default = default)
265                 self.durationlength = ConfigNumber(default = duration)
266
267                 # Counter
268                 if timer.hasCounter():
269                         default = timer.matchCount
270                 else:
271                         default = 0
272                 self.counter = ConfigNumber(default = default)
273                 self.counterLeft = ConfigNumber(default = timer.matchLeft)
274                 selection = [("", _("Never")), ("%m", _("Monthly")), ("%U", _("Weekly (Sunday)")), ("%W", _("Weekly (Monday)"))]
275                 if timer.getCounterFormatString() not in ["", "%m", "%U", "%W"]:
276                         selection.append((timer.getCounterFormatString(), _("Custom (%s)") % (timer.getCounterFormatString())))
277                 self.counterFormatString = ConfigSelection(selection, default = timer.getCounterFormatString())
278
279                 # Avoid Duplicate Description
280                 self.avoidDuplicateDescription = ConfigEnableDisable(default = timer.getAvoidDuplicateDescription())
281
282                 # Custom Location
283                 self.destination = ConfigSelection(choices = [timer.destination or "/hdd/movie/"])
284
285         def refresh(self):
286                 # First four entries are always shown
287                 self.list = [
288                         getConfigListEntry(_("Enabled"), self.enabled),
289                         getConfigListEntry(_("Description"), self.name),
290                         getConfigListEntry(_("Match Title"), self.match),
291                         getConfigListEntry(_("Timer Type"), self.justplay),
292                         getConfigListEntry(_("Only match during Timespan"), self.timespan)
293                 ]
294
295                 # Only allow editing timespan when it's enabled
296                 if self.timespan.value:
297                         self.list.extend([
298                                 getConfigListEntry(_("Begin of Timespan"), self.timespanbegin),
299                                 getConfigListEntry(_("End of Timespan"), self.timespanend)
300                         ])
301
302                 self.list.append(getConfigListEntry(_("Custom offset"), self.offset))
303
304                 # Only allow editing offsets when it's enabled
305                 if self.offset.value:
306                         self.list.extend([
307                                 getConfigListEntry(_("Offset before recording (in m)"), self.offsetbegin),
308                                 getConfigListEntry(_("Offset after recording (in m)"), self.offsetend)
309                         ])
310
311                 self.list.append(getConfigListEntry(_("Set maximum Duration"), self.duration))
312
313                 # Only allow editing maxduration when it's enabled
314                 if self.duration.value:
315                         self.list.extend([
316                                 getConfigListEntry(_("Maximum Duration (in m)"), self.durationlength)
317                         ])
318
319                 self.list.append(getConfigListEntry(_("After event"), self.afterevent))
320
321                 # Only allow setting afterevent timespan when afterevent is active
322                 if self.afterevent.value != "default":
323                         self.list.append(getConfigListEntry(_("Execute after Event during Timespan"), self.afterevent_timespan))
324
325                         # Only allow editing timespan when it's enabled
326                         if self.afterevent_timespan.value:
327                                 self.list.extend([
328                                         getConfigListEntry(_("Begin of after Event Timespan"), self.afterevent_timespanbegin),
329                                         getConfigListEntry(_("End of after Event Timespan"), self.afterevent_timespanend)
330                                 ])
331
332                 self.list.append(getConfigListEntry(_("Record a maximum of x times"), self.counter))
333
334                 # Only allow setting matchLeft when counting hits
335                 if self.counter.value:
336                         self.list.append(getConfigListEntry(_("Ammount of recordings left"), self.counterLeft))
337                         self.list.append(getConfigListEntry(_("Reset Count"), self.counterFormatString))
338
339                 self.list.append(getConfigListEntry(_("Require Description to be unique"), self.avoidDuplicateDescription))
340
341                 # We always add this option though its actually expert only
342                 self.list.append(getConfigListEntry(_("Custom Location"), self.destination))
343
344         def reloadList(self, value):
345                 self.refresh()
346                 self["config"].setList(self.list)
347
348         def editFilter(self):
349                 self.session.openWithCallback(
350                         self.editFilterCallback,
351                         AutoTimerFilterEditor,
352                         self.filterSet,
353                         self.excludes,
354                         self.includes
355                 )
356
357         def editFilterCallback(self, ret):
358                 if ret:
359                         self.filterSet = ret[0]
360                         self.excludes = ret[1]
361                         self.includes = ret[2]
362                         self.renameFilterButton()
363
364         def editServices(self):
365                 self.session.openWithCallback(
366                         self.editServicesCallback,
367                         AutoTimerServiceEditor,
368                         self.serviceRestriction,
369                         self.services,
370                         self.bouquets
371                 )
372
373         def editServicesCallback(self, ret):
374                 if ret:
375                         self.serviceRestriction = ret[0]
376                         self.services = ret[1][0]
377                         self.bouquets = ret[1][1]
378                         self.renameServiceButton()
379
380         def ok(self):
381                 cur = self["config"].getCurrent()
382                 cur = cur and cur[1]
383                 if cur == self.destination:
384                         from Screens.LocationBox import LocationBox
385
386                         self.session.openWithCallback(
387                                 self.pathSelected,
388                                 LocationBox,
389                                 text = _("Choose target folder"),
390                                 filename = "",
391                                 currDir = self.destination.value
392                         )
393                 else:
394                         ConfigListScreen.keyOK(self)
395
396         def pathSelected(self, res):
397                 if res is not None:
398                         self.destination.choices.append(res)
399                         self.destination.description[res] = res
400                         self.destination.value = res
401
402         def cancel(self):
403                 if self["config"].isChanged():
404                         self.session.openWithCallback(
405                                 self.cancelConfirm,
406                                 MessageBox,
407                                 _("Really close without saving settings?")
408                         )
409                 else:
410                         self.close(None)
411
412         def cancelConfirm(self, ret):
413                 if ret:
414                         self.close(None)
415
416         def maybeSave(self):
417                 # Check if we have a trailing whitespace
418                 if self.match.value[-1:] == " ":
419                         self.session.openWithCallback(
420                                 self.saveCallback,
421                                 MessageBox,
422                                 _('You entered "%s" as Text to match.\nDo you want to remove trailing whitespaces?') % (self.match.value)
423                         )
424                 # Just save else
425                 else:
426                         self.save()
427
428         def saveCallback(self, ret):
429                 if ret is not None:
430                         if ret:
431                                 self.match.value = self.match.value.rstrip()
432                         self.save()
433                 # Don't to anything if MessageBox was canceled!
434
435         def save(self):
436                 # Match
437                 self.timer.match = self.match.value
438
439                 # Name
440                 self.timer.name = self.name.value or self.timer.match
441
442                 # Enabled
443                 self.timer.enabled = self.enabled.value
444
445                 # Justplay
446                 self.timer.justplay = self.justplay.value == "zap"
447
448                 # Timespan
449                 if self.timespan.value:
450                         start = self.timespanbegin.value
451                         end = self.timespanend.value
452                         self.timer.timespan = (start, end)
453                 else:
454                         self.timer.timespan = None
455
456                 # Services
457                 if self.serviceRestriction:
458                         self.timer.services = self.services
459                         self.timer.bouquets = self.bouquets
460                 else:
461                         self.timer.services = None
462                         self.timer.bouquets = None
463
464                 # Offset
465                 if self.offset.value:
466                         self.timer.offset = (self.offsetbegin.value*60, self.offsetend.value*60)
467                 else:
468                         self.timer.offset = None
469
470                 # AfterEvent
471                 if self.afterevent.value == "default":
472                         self.timer.afterevent = []
473                 else:
474                         afterevent = {"nothing": AFTEREVENT.NONE, "deepstandby": AFTEREVENT.DEEPSTANDBY, "standby": AFTEREVENT.STANDBY}[self.afterevent.value]
475                         # AfterEvent Timespan
476                         if self.afterevent_timespan.value:
477                                 start = self.afterevent_timespanbegin.value
478                                 end = self.afterevent_timespanend.value
479                                 self.timer.afterevent = [(afterevent, (start, end))]
480                         else:
481                                 self.timer.afterevent = [(afterevent, None)]
482
483                 # Maxduration
484                 if self.duration.value:
485                         self.timer.maxduration = self.durationlength.value*60
486                 else:
487                         self.timer.maxduration = None
488
489                 # Ex-&Includes
490                 if self.filterSet:
491                         self.timer.exclude = self.excludes
492                         self.timer.include = self.includes
493                 else:
494                         self.timer.exclude = None
495                         self.timer.include = None
496
497                 # Counter
498                 if self.counter.value:
499                         self.timer.matchCount = self.counter.value
500                         if self.counterLeft.value <= self.counter.value:
501                                 self.timer.matchLeft = self.counterLeft.value
502                         else:
503                                 self.timer.matchLeft = self.counter.value
504                         if self.counterFormatString.value:
505                                 self.timer.matchFormatString = self.counterFormatString.value
506                         else:
507                                 self.timer.matchFormatString = ''
508                 else:
509                         self.timer.matchCount = 0
510                         self.timer.matchLeft = 0
511                         self.timer.matchFormatString = ''
512
513                 self.timer.avoidDuplicateDescription = self.avoidDuplicateDescription.value
514
515                 if self.destination.value == "/hdd/movie/":
516                         self.timer.destination = None
517                 else:
518                         self.timer.destination = self.destination.value
519
520                 # Close
521                 self.close(self.timer)
522
523 class AutoTimerFilterEditor(Screen, ConfigListScreen):
524         """Edit AutoTimer Filter"""
525
526         skin = """<screen name="AutoFilterEditor" title="Edit AutoTimer Filters" position="75,150" size="565,245">
527                 <widget name="config" position="5,5" size="555,200" scrollbarMode="showOnDemand" />
528                 <ePixmap position="5,205" zPosition="4" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
529                 <ePixmap position="145,205" zPosition="4" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
530                 <ePixmap position="285,205" zPosition="4" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
531                 <ePixmap position="425,205" zPosition="4" size="140,40" pixmap="skin_default/buttons/blue.png" transparent="1" alphatest="on" />
532                 <widget name="key_red" position="5,205" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
533                 <widget name="key_green" position="145,205" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
534                 <widget name="key_yellow" position="285,205" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
535                 <widget name="key_blue" position="425,205" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
536         </screen>"""
537
538         def __init__(self, session, filterset, excludes, includes):
539                 Screen.__init__(self, session)
540
541                 # Summary
542                 self.setup_title = "AutoTimer Filters"
543                 self.onChangedEntry = []
544
545                 self.typeSelection = ConfigSelection(choices = [("title", _("in Title")), ("short", _("in Shortdescription")), ("desc", _("in Description")), ("day", _("on Weekday"))])
546                 self.typeSelection.addNotifier(self.refresh, initial_call = False)
547
548                 self.enabled = ConfigEnableDisable(default = filterset)
549
550                 self.excludes = excludes
551                 self.includes = includes
552
553                 self.reloadList()
554
555                 ConfigListScreen.__init__(self, self.list, session = session, on_change = self.changed)
556
557                 # Initialize Buttons
558                 self["key_red"] = Button(_("Cancel"))
559                 self["key_green"] = Button(_("Save"))
560                 self["key_yellow"] = Button(_("delete"))
561                 self["key_blue"] = Button(_("New"))
562
563                 # Define Actions
564                 self["actions"] = ActionMap(["SetupActions", "ColorActions"],
565                         {
566                                 "cancel": self.cancel,
567                                 "save": self.save,
568                                 "yellow": self.remove,
569                                 "blue": self.new
570                         }
571                 )
572
573                 # Trigger change
574                 self.changed()
575
576         def changed(self):
577                 for x in self.onChangedEntry:
578                         try:
579                                 x()
580                         except:
581                                 pass
582
583         def getCurrentEntry(self):
584                 return self["config"].getCurrent()[0]
585
586         def getCurrentValue(self):
587                 return str(self["config"].getCurrent()[1].getText())
588
589         def createSummary(self):
590                 return SetupSummary
591
592         def saveCurrent(self):
593                 del self.excludes[self.idx][:]
594                 del self.includes[self.idx][:]
595
596                 # Warning, accessing a ConfigListEntry directly might be considered evil!
597
598                 idx = -1
599                 for item in self["config"].getList():
600                         idx += 1
601                         # Skip empty entries (and those which are no filters)
602                         if item[1].value == "" or idx < 2:
603                                 continue
604                         elif idx < self.lenExcludes:
605                                 self.excludes[self.idx].append(item[1].value.encode("UTF-8"))
606                         else:
607                                 self.includes[self.idx].append(item[1].value.encode("UTF-8"))
608
609         def refresh(self, value):
610                 self.saveCurrent()
611
612                 self.reloadList()
613                 self["config"].setList(self.list)
614
615         def reloadList(self):
616                 self.list = [
617                         getConfigListEntry(_("Enable Filtering"), self.enabled),
618                         getConfigListEntry(_("Filter"), self.typeSelection)
619                 ]
620
621                 if self.typeSelection.value == "day":
622                         self.idx = 3
623
624                         # Weekdays are presented as ConfigSelection
625                         self.list.extend([
626                                 getConfigListEntry(_("Exclude"), ConfigSelection(choices = weekdays, default = x))
627                                         for x in self.excludes[3]
628                         ])
629                         self.lenExcludes = len(self.list)
630                         self.list.extend([
631                                 getConfigListEntry(_("Include"), ConfigSelection(choices = weekdays, default = x))
632                                         for x in self.includes[3]
633                         ])
634                         return
635                 elif self.typeSelection.value == "title":
636                         self.idx = 0
637                 elif self.typeSelection.value == "short":
638                         self.idx = 1
639                 else: # self.typeSelection.value == "desc":
640                         self.idx = 2
641
642                 self.list.extend([
643                         getConfigListEntry(_("Exclude"), ConfigText(default = x, fixed_size = False))
644                                 for x in self.excludes[self.idx]
645                 ])
646                 self.lenExcludes = len(self.list)
647                 self.list.extend([
648                         getConfigListEntry(_("Include"), ConfigText(default = x, fixed_size = False))
649                                 for x in self.includes[self.idx]
650                 ])
651
652         def remove(self):
653                 idx = self["config"].getCurrentIndex()
654                 if idx and idx > 1:
655                         if idx < self.lenExcludes:
656                                 self.lenExcludes -= 1
657
658                         list = self["config"].getList()
659                         list.remove(self["config"].getCurrent())
660                         self["config"].setList(list)
661
662         def new(self):
663                 self.session.openWithCallback(
664                         self.typeSelected,
665                         ChoiceBox,
666                         _("Select type of Filter"),
667                         [
668                                 (_("Exclude"), 0),
669                                 (_("Include"), 1),
670                         ]
671                 )
672
673         def typeSelected(self, ret):
674                 if ret is not None:
675                         list = self["config"].getList()
676
677                         if ret[1] == 0:
678                                 pos = self.lenExcludes
679                                 self.lenExcludes += 1
680                                 text = ret[0]
681                         else:
682                                 pos = len(self.list)
683                                 text = ret[0]
684
685                         if self.typeSelection.value == "day":
686                                 entry = getConfigListEntry(text, ConfigSelection(choices = weekdays))
687                         else:
688                                 entry = getConfigListEntry(text, ConfigText(fixed_size = False))
689
690                         list.insert(pos, entry)
691                         self["config"].setList(list)
692
693         def cancel(self):
694                 if self["config"].isChanged():
695                         self.session.openWithCallback(
696                                 self.cancelConfirm,
697                                 MessageBox,
698                                 _("Really close without saving settings?")
699                         )
700                 else:
701                         self.close(None)
702
703         def cancelConfirm(self, ret):
704                 if ret:
705                         self.close(None)
706
707         def save(self):
708                 self.saveCurrent()
709
710                 self.close((
711                         self.enabled.value,
712                         self.excludes,
713                         self.includes
714                 ))
715
716 class AutoTimerServiceEditor(Screen, ConfigListScreen):
717         """Edit allowed Services of a AutoTimer"""
718
719         skin = """<screen name="AutoTimerServiceEditor" title="Edit AutoTimer Services" position="75,150" size="565,245">
720                 <widget name="config" position="5,5" size="555,200" scrollbarMode="showOnDemand" />
721                 <ePixmap position="5,205" zPosition="4" size="140,40" pixmap="skin_default/buttons/red.png" transparent="1" alphatest="on" />
722                 <ePixmap position="145,205" zPosition="4" size="140,40" pixmap="skin_default/buttons/green.png" transparent="1" alphatest="on" />
723                 <ePixmap position="285,205" zPosition="4" size="140,40" pixmap="skin_default/buttons/yellow.png" transparent="1" alphatest="on" />
724                 <ePixmap position="425,205" zPosition="4" size="140,40" pixmap="skin_default/buttons/blue.png" transparent="1" alphatest="on" />
725                 <widget name="key_red" position="5,205" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
726                 <widget name="key_green" position="145,205" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
727                 <widget name="key_yellow" position="285,205" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
728                 <widget name="key_blue" position="425,205" zPosition="5" size="140,40" valign="center" halign="center" font="Regular;21" transparent="1" foregroundColor="white" shadowColor="black" shadowOffset="-1,-1" />
729         </screen>"""
730
731         def __init__(self, session, servicerestriction, servicelist, bouquetlist):
732                 Screen.__init__(self, session)
733
734                 # Summary
735                 self.setup_title = "AutoTimer Services"
736                 self.onChangedEntry = []
737
738                 self.services = (
739                         servicelist[:],
740                         bouquetlist[:]
741                 )
742
743                 self.enabled = ConfigEnableDisable(default = servicerestriction)
744                 self.typeSelection = ConfigSelection(choices = [("channels", _("Channels")), ("bouquets", _("Bouquets"))])
745                 self.typeSelection.addNotifier(self.refresh, initial_call = False)
746
747                 self.reloadList()
748
749                 ConfigListScreen.__init__(self, self.list, session = session, on_change = self.changed)
750
751                 # Initialize Buttons
752                 self["key_red"] = Button(_("Cancel"))
753                 self["key_green"] = Button(_("OK"))
754                 self["key_yellow"] = Button(_("delete"))
755                 self["key_blue"] = Button(_("New"))
756
757                 # Define Actions
758                 self["actions"] = ActionMap(["SetupActions", "ColorActions"],
759                         {
760                                 "cancel": self.cancel,
761                                 "save": self.save,
762                                 "yellow": self.remove,
763                                 "blue": self.new
764                         }
765                 )
766
767                 # Trigger change
768                 self.changed()
769
770         
771         def saveCurrent(self):
772                 del self.services[self.idx][:]
773                 
774                 # Warning, accessing a ConfigListEntry directly might be considered evil!
775
776                 myl = self["config"].getList()
777                 myl.pop(0) # Enabled
778                 myl.pop(0) # Type
779                 for item in myl:
780                         self.services[self.idx].append(item[1].value)
781
782         def refresh(self, value):
783                 self.saveCurrent()
784
785                 self.reloadList()
786                 self["config"].setList(self.list)
787
788         def reloadList(self):
789                 self.list = [
790                         getConfigListEntry(_("Enable Service Restriction"), self.enabled),
791                         getConfigListEntry(_("Editing"), self.typeSelection)
792                 ]
793                 
794                 if self.typeSelection.value == "channels":
795                         self.idx = 0
796                 else: # self.typeSelection.value == "bouquets":
797                         self.idx = 1
798
799                 self.list.extend([
800                         getConfigListEntry(_("Record on"), ConfigSelection(choices = [(str(x), ServiceReference(str(x)).getServiceName().replace('\xc2\x86', '').replace('\xc2\x87', ''))]))
801                                 for x in self.services[self.idx]
802                 ])
803
804         def changed(self):
805                 for x in self.onChangedEntry:
806                         try:
807                                 x()
808                         except:
809                                 pass
810
811         def getCurrentEntry(self):
812                 return self["config"].getCurrent()[0]
813
814         def getCurrentValue(self):
815                 return str(self["config"].getCurrent()[1].getText())
816
817         def createSummary(self):
818                 return SetupSummary
819
820         def remove(self):
821                 if self["config"].getCurrentIndex() != 0:
822                         list = self["config"].getList()
823                         list.remove(self["config"].getCurrent())
824                         self["config"].setList(list)
825
826         def new(self):
827                 if self.typeSelection.value == "channels":
828                         self.session.openWithCallback(
829                                 self.finishedServiceSelection,
830                                 SimpleChannelSelection,
831                                 _("Select channel to record on")
832                         )
833                 else: # self.typeSelection.value == "bouquets":
834                         self.session.openWithCallback(
835                                 self.finishedServiceSelection,
836                                 SimpleBouquetSelection,
837                                 _("Select bouquet to record on")
838                         )
839
840         def finishedServiceSelection(self, *args):
841                 if len(args):
842                         list = self["config"].getList()
843                         sname = args[0].toString()
844
845                         if self.typeSelection.value == "channels":
846                                 # strip all after last : when adding a channel
847                                 pos = sname.rfind(':')
848                                 if pos != -1:
849                                         sname = sname[:pos+1]
850
851                         list.append(getConfigListEntry(_("Record on"), ConfigSelection(choices = [(sname, ServiceReference(args[0]).getServiceName().replace('\xc2\x86', '').replace('\xc2\x87', ''))])))
852                         self["config"].setList(list)
853
854         def cancel(self):
855                 if self["config"].isChanged():
856                         self.session.openWithCallback(
857                                 self.cancelConfirm,
858                                 MessageBox,
859                                 _("Really close without saving settings?")
860                         )
861                 else:
862                         self.close(None)
863
864         def cancelConfirm(self, ret):
865                 if ret:
866                         self.close(None)
867
868         def save(self):
869                 self.saveCurrent()
870
871                 self.close((
872                         self.enabled.value,
873                         self.services
874                 ))
875
876 def addAutotimerFromEvent(session, evt = None, service = None):
877         from AutoTimerComponent import AutoTimerComponent
878         from AutoTimerImporter import AutoTimerImporter
879         from plugin import autotimer
880                 
881         # Create instance if needed
882         if autotimer is None:
883                 from AutoTimer import AutoTimer
884                 autotimer = AutoTimer()
885
886         match = evt and evt.getEventName() or ""
887         name = match or "New AutoTimer"
888         sref = None
889         if service is not None:
890                 service = str(service)
891                 # strip all after last :
892                 pos = service.rfind(':')
893                 if pos != -1:
894                         service = service[:pos+1]
895
896                 sref = ServiceReference(service)
897         if evt:
898                  # timespan defaults to +- 1h
899                 begin = evt.getBeginTime()-3600
900                 end = begin + evt.getDuration()+7200
901         else:
902                 begin = end = 0
903
904         # XXX: we might want to make sure that we actually collected any data because the importer does not do so :-)
905
906         session.openWithCallback(
907                 importerCallback,
908                 AutoTimerImporter,
909                 AutoTimerComponent(
910                         autotimer.getUniqueId(),                # Id
911                         name,                                                   # Name
912                         "",                                                             # Match
913                         True                                                    # Enabled
914                 ),
915                 match,                     # Proposed Match
916                 begin,                     # Proposed Begin
917                 end,                       # Proposed End
918                 None,                      # Proposed Disabled
919                 sref,                      # Proposed ServiceReference
920                 None,                  # Proposed afterEvent 
921                 None,                      # Proposed justplay 
922                 None                       # Proposed dirname, can we get anything useful here? 
923         )
924
925 def addAutotimerFromService(session, service = None):   
926         from AutoTimerComponent import AutoTimerComponent
927         from AutoTimerImporter import AutoTimerImporter
928         from plugin import autotimer
929                 
930         # Create instance if needed
931         if autotimer is None:
932                 from AutoTimer import AutoTimer
933                 autotimer = AutoTimer()
934
935         serviceHandler = eServiceCenter.getInstance()
936         info = serviceHandler.info(service)
937
938         match = info and info.getName(service) or ""
939         name = match or "New AutoTimer"
940         sref = info and info.getInfoString(service, iServiceInformation.sServiceref)
941         if sref:
942                 # strip all after last :
943                 pos = sref.rfind(':')
944                 if pos != -1:
945                         sref = sref[:pos+1]
946
947                 sref = ServiceReference(sref)
948         if info:
949                 begin = info.getInfo(service, iServiceInformation.sTimeCreate)
950                 end = begin + info.getLength(service)
951         else:
952                 begin = end = 0
953
954         # XXX: we might want to make sure that we actually collected any data because the importer does not do so :-)
955
956         session.openWithCallback(
957                 importerCallback,
958                 AutoTimerImporter,
959                 AutoTimerComponent(
960                         autotimer.getUniqueId(),                # Id
961                         name,                                                   # Name
962                         "",                                                             # Match
963                         True                                                    # Enabled
964                 ),
965                 match,                     # Proposed Match
966                 begin,                     # Proposed Begin
967                 end,                       # Proposed End
968                 None,                      # Proposed Disabled
969                 sref,                      # Proposed ServiceReference
970                 None,                  # Proposed afterEvent 
971                 None,                      # Proposed justplay 
972                 None                       # Proposed dirname, can we get anything useful here? 
973         )
974
975 def importerCallback(ret):
976         if ret:
977                 ret, session = ret
978                 
979                 session.openWithCallback(
980                         editorCallback,
981                         AutoTimerEditor,
982                         ret
983                 )
984         else:
985                 # Remove instance if not running in background
986                 if not config.plugins.autotimer.autopoll.value:
987                         from plugin import autotimer
988                         autotimer = None
989
990
991 def editorCallback(ret):
992         if ret:
993                 from plugin import autotimer
994                 
995                 # Create instance if needed (should have been created by addAutotimerFrom* above though)
996                 if autotimer is None:
997                         from AutoTimer import AutoTimer
998                         autotimer = AutoTimer()
999
1000                 autotimer.add(ret)
1001                 
1002         # Remove instance if not running in background
1003         if not config.plugins.autotimer.autopoll.value:
1004                 # Save xml (as long as we added something)
1005                 ret and autotimer and autotimer.writeXml()
1006                 autotimer = None