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