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