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