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