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