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