2 from Screens.Screen import Screen
3 from Components.ConfigList import ConfigListScreen
4 from Screens.ChannelSelection import SimpleChannelSelection
5 from Screens.MessageBox import MessageBox
6 from Screens.ChoiceBox import ChoiceBox
9 from Screens.Setup import SetupSummary
12 from Components.ActionMap import ActionMap
13 from Components.Button import Button
16 from Components.config import getConfigListEntry, ConfigEnableDisable, ConfigYesNo, ConfigText, ConfigClock, ConfigInteger, ConfigSelection
19 from RecordTimer import AFTEREVENT
21 # Needed to convert our timestamp back and forth
22 from time import localtime, mktime
24 # Show ServiceName instead of ServiceReference
25 from ServiceReference import ServiceReference
27 weekdays = [("0", _("Monday")), ("1", _("Tuesday")), ("2", _("Wednesday")), ("3", _("Thursday")), ("4", _("Friday")), ("5", _("Saturday")), ("6", _("Sunday")), ("weekend", _("Weekend")), ("weekday", _("Weekday"))]
29 class AutoTimerEditor(Screen, ConfigListScreen):
32 skin = """<screen name="AutoTimerEdit" title="Edit AutoTimer" position="75,155" size="565,280">
33 <widget name="config" position="5,5" size="555,225" scrollbarMode="showOnDemand" />
34 <ePixmap position="0,235" zPosition="4" size="140,40" pixmap="skin_default/key-red.png" transparent="1" alphatest="on" />
35 <ePixmap position="140,235" zPosition="4" size="140,40" pixmap="skin_default/key-green.png" transparent="1" alphatest="on" />
36 <ePixmap position="280,235" zPosition="4" size="140,40" pixmap="skin_default/key-yellow.png" transparent="1" alphatest="on" />
37 <ePixmap position="420,235" zPosition="4" size="140,40" pixmap="skin_default/key-blue.png" transparent="1" alphatest="on" />
38 <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" />
39 <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" />
40 <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" />
41 <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" />
44 def __init__(self, session, timer):
45 Screen.__init__(self, session)
51 self.setup_title = "AutoTimer Editor"
52 self.onChangedEntry = []
54 # See if we are filtering some strings
56 timer.getExcludedTitle(),
57 timer.getExcludedShort(),
58 timer.getExcludedDescription(),
59 timer.getExcludedDays()
62 timer.getIncludedTitle(),
63 timer.getIncludedShort(),
64 timer.getIncludedDescription(),
65 timer.getIncludedDays()
67 if len(self.excludes[0]) or len(self.excludes[1]) or len(self.excludes[2]) \
68 or len(self.excludes[3]) or len(self.includes[0]) or len(self.includes[1]) \
69 or len(self.includes[2]) or len(self.includes[3]):
72 self.filterSet = False
74 # See if services are restricted
75 self.services = timer.getServices()
76 if len(self.services):
77 self.serviceRestriction = True
79 self.serviceRestriction = False
81 self.createSetup(timer)
83 # We might need to change shown items, so add some notifiers
84 self.timespan.addNotifier(self.reloadList, initial_call = False)
85 self.offset.addNotifier(self.reloadList, initial_call = False)
86 self.duration.addNotifier(self.reloadList, initial_call = False)
87 self.afterevent.addNotifier(self.reloadList, initial_call = False)
88 self.afterevent_timespan.addNotifier(self.reloadList, initial_call = False)
89 self.counter.addNotifier(self.reloadList, initial_call = False)
93 ConfigListScreen.__init__(self, self.list, session = session, on_change = self.changed)
96 self["key_red"] = Button(_("Cancel"))
97 self["key_green"] = Button(_("OK"))
98 self["key_yellow"] = Button()
99 self["key_blue"] = Button()
102 self.renameChannelButton()
103 self.renameFilterButton()
106 self["actions"] = ActionMap(["SetupActions", "ColorActions"],
108 "cancel": self.cancel,
109 "save": self.maybeSave,
110 "yellow": self.editFilter,
111 "blue": self.editChannels
118 def renameFilterButton(self):
120 self["key_yellow"].setText(_("Edit Filters"))
122 self["key_yellow"].setText(_("Add Filters"))
124 def renameChannelButton(self):
125 if self.serviceRestriction:
126 self["key_blue"].setText(_("Edit Channels"))
128 self["key_blue"].setText(_("Add Channels"))
131 for x in self.onChangedEntry:
137 def getCurrentEntry(self):
138 return self["config"].getCurrent()[0]
140 def getCurrentValue(self):
141 return str(self["config"].getCurrent()[1].getText())
143 def createSummary(self):
146 def createSetup(self, timer):
148 self.name = ConfigText(default = timer.name, fixed_size = False)
151 self.match = ConfigText(default = timer.match, fixed_size = False)
154 self.justplay = ConfigSelection(choices = [("zap", _("zap")), ("record", _("record"))], default = {0: "record", 1: "zap"}[int(timer.justplay)])
157 now = [x for x in localtime()]
158 if timer.hasTimespan():
160 now[3] = timer.timespan[0][0]
161 now[4] = timer.timespan[0][1]
163 now[3] = timer.timespan[1][0]
164 now[4] = timer.timespan[1][1]
174 self.timespan = ConfigEnableDisable(default = default)
175 self.timespanbegin = ConfigClock(default = begin)
176 self.timespanend = ConfigClock(default = end)
178 # Services have their own Screen
181 if timer.hasOffset():
183 begin = timer.getOffsetBegin()
184 end = timer.getOffsetEnd()
189 self.offset = ConfigEnableDisable(default = default)
190 self.offsetbegin = ConfigInteger(default = begin, limits = (0, 60))
191 self.offsetend = ConfigInteger(default = end, limits = (0, 60))
194 if timer.hasAfterEvent():
195 afterevent = { None: "default", AFTEREVENT.NONE: "nothing", AFTEREVENT.DEEPSTANDBY: "deepstandby", AFTEREVENT.STANDBY: "standby"}[timer.afterevent[0][0]]
197 afterevent = "default"
198 self.afterevent = ConfigSelection(choices = [("default", _("standard")), ("nothing", _("do nothing")), ("standby", _("go to standby")), ("deepstandby", _("go to deep standby"))], default = afterevent)
200 # AfterEvent (Timespan)
201 if timer.hasAfterEvent() and timer.afterevent[0][1][0] is not None:
203 now[3] = timer.afterevent[0][1][0][0]
204 now[4] = timer.afterevent[0][1][0][1]
206 now[3] = timer.afterevent[0][1][1][0]
207 now[4] = timer.afterevent[0][1][1][1]
217 self.afterevent_timespan = ConfigEnableDisable(default = default)
218 self.afterevent_timespanbegin = ConfigClock(default = begin)
219 self.afterevent_timespanend = ConfigClock(default = end)
222 self.enabled = ConfigYesNo(default = timer.enabled)
225 if timer.hasDuration():
227 duration = timer.getDuration()
231 self.duration = ConfigEnableDisable(default = default)
232 self.durationlength = ConfigInteger(default = duration, limits = (0, 600))
235 if timer.hasCounter():
236 default = timer.matchCount
239 self.counter = ConfigInteger(default = default, limits = (0, 50))
240 self.counterLeft = ConfigInteger(default = timer.matchLeft, limits = (0, 50))
241 selection = [("", _("Never")), ("%m", _("Monthly")), ("%U", _("Weekly (Sunday)")), ("%W", _("Weekly (Monday)"))]
242 if timer.getCounterFormatString() not in ["", "%m", "%U", "%W"]:
243 selection.append((timer.getCounterFormatString(), _("Custom")))
244 self.counterFormatString = ConfigSelection(selection, default = timer.getCounterFormatString())
246 # Avoid Duplicate Description
247 self.avoidDuplicateDescription = ConfigEnableDisable(default = timer.getAvoidDuplicateDescription())
250 # First four entries are always shown
252 getConfigListEntry(_("Enabled"), self.enabled),
253 getConfigListEntry(_("Description"), self.name),
254 getConfigListEntry(_("Match Title"), self.match),
255 getConfigListEntry(_("Timer Type"), self.justplay),
256 getConfigListEntry(_("Only match during Timespan"), self.timespan)
259 # Only allow editing timespan when it's enabled
260 if self.timespan.value:
262 getConfigListEntry(_("Begin of Timespan"), self.timespanbegin),
263 getConfigListEntry(_("End of Timespan"), self.timespanend)
266 self.list.append(getConfigListEntry(_("Custom offset"), self.offset))
268 # Only allow editing offsets when it's enabled
269 if self.offset.value:
271 getConfigListEntry(_("Offset before recording (in m)"), self.offsetbegin),
272 getConfigListEntry(_("Offset after recording (in m)"), self.offsetend)
275 self.list.append(getConfigListEntry(_("Set maximum Duration"), self.duration))
277 # Only allow editing maxduration when it's enabled
278 if self.duration.value:
280 getConfigListEntry(_("Maximum Duration (in m)"), self.durationlength)
283 self.list.append(getConfigListEntry(_("After event"), self.afterevent))
285 # Only allow setting afterevent timespan when afterevent is active
286 if self.afterevent.value != "default":
287 self.list.append(getConfigListEntry(_("Execute after Event during Timespan"), self.afterevent_timespan))
289 # Only allow editing timespan when it's enabled
290 if self.afterevent_timespan.value:
292 getConfigListEntry(_("Begin of after Event Timespan"), self.afterevent_timespanbegin),
293 getConfigListEntry(_("End of after Event Timespan"), self.afterevent_timespanend)
296 self.list.append(getConfigListEntry(_("Record a maximum of x times"), self.counter))
298 # Only allow setting matchLeft when counting hits
299 if self.counter.value:
300 self.list.append(getConfigListEntry(_("Ammount of recordings left"), self.counterLeft))
301 self.list.append(getConfigListEntry(_("Reset Count"), self.counterFormatString))
303 self.list.append(getConfigListEntry(_("Require Description to be unique"), self.avoidDuplicateDescription))
305 def reloadList(self, value):
307 self["config"].setList(self.list)
309 def editFilter(self):
310 self.session.openWithCallback(
311 self.editFilterCallback,
312 AutoTimerFilterEditor,
318 def editFilterCallback(self, ret):
320 self.filterSet = ret[0]
321 self.excludes = ret[1]
322 self.includes = ret[2]
323 self.renameFilterButton()
325 def editChannels(self):
326 self.session.openWithCallback(
327 self.editChannelsCallback,
328 AutoTimerChannelEditor,
329 self.serviceRestriction,
333 def editChannelsCallback(self, ret):
335 self.serviceRestriction = ret[0]
336 self.services = ret[1]
337 self.renameChannelButton()
340 if self["config"].isChanged():
341 self.session.openWithCallback(self.cancelConfirm, MessageBox, _("Really close without saving settings?"))
345 def cancelConfirm(self, ret):
350 # Check if we have a trailing whitespace
351 if self.match.value[-1:] == " ":
352 self.session.openWithCallback(
355 _('You entered "%s" as Text to match.\nDo you want to remove trailing whitespaces?') % (self.match.value)
361 def saveCallback(self, ret):
364 self.match.value = self.match.value.rstrip()
366 # Don't to anything if MessageBox was canceled!
370 self.timer.match = self.match.value
373 self.timer.name = self.name.value or self.timer.match
376 self.timer.enabled = self.enabled.value
379 self.timer.justplay = self.justplay.value == "zap"
382 if self.timespan.value:
383 start = self.timespanbegin.value
384 end = self.timespanend.value
385 self.timer.timespan = (start, end)
387 self.timer.timespan = None
390 if self.serviceRestriction:
391 self.timer.services = self.services
393 self.timer.services = None
396 if self.offset.value:
397 self.timer.offset = (self.offsetbegin.value*60, self.offsetend.value*60)
399 self.timer.offset = None
402 if self.afterevent.value == "default":
403 self.timer.afterevent = []
405 afterevent = {"nothing": AFTEREVENT.NONE, "deepstandby": AFTEREVENT.DEEPSTANDBY, "standby": AFTEREVENT.STANDBY}[self.afterevent.value]
406 # AfterEvent Timespan
407 if self.afterevent_timespan.value:
408 start = self.afterevent_timespanbegin.value
409 end = self.afterevent_timespanend.value
410 self.timer.afterevent = [(afterevent, (start, end))]
412 self.timer.afterevent = [(afterevent, None)]
415 if self.duration.value:
416 self.timer.maxduration = self.durationlength.value*60
418 self.timer.maxduration = None
422 self.timer.exclude = self.excludes
423 self.timer.include = self.includes
425 self.timer.exclude = None
426 self.timer.include = None
429 if self.counter.value:
430 self.timer.matchCount = self.counter.value
431 if self.counterLeft.value <= self.counter.value:
432 self.timer.matchLeft = self.counterLeft.value
434 self.timer.matchLeft = self.counter.value
435 if self.counterFormatString.value:
436 self.timer.matchFormatString = self.counterFormatString.value
438 self.timer.matchFormatString = ''
440 self.timer.matchCount = 0
441 self.timer.matchLeft = 0
442 self.timer.matchFormatString = ''
444 self.timer.avoidDuplicateDescription = self.avoidDuplicateDescription.value
447 self.close(self.timer)
449 class AutoTimerFilterEditor(Screen, ConfigListScreen):
450 """Edit AutoTimer Filter"""
452 skin = """<screen name="AutoFilterEditor" title="Edit AutoTimer Filters" position="75,150" size="565,245">
453 <widget name="config" position="5,5" size="555,200" scrollbarMode="showOnDemand" />
454 <ePixmap position="5,205" zPosition="4" size="140,40" pixmap="skin_default/key-red.png" transparent="1" alphatest="on" />
455 <ePixmap position="145,205" zPosition="4" size="140,40" pixmap="skin_default/key-green.png" transparent="1" alphatest="on" />
456 <ePixmap position="285,205" zPosition="4" size="140,40" pixmap="skin_default/key-yellow.png" transparent="1" alphatest="on" />
457 <ePixmap position="425,205" zPosition="4" size="140,40" pixmap="skin_default/key-blue.png" transparent="1" alphatest="on" />
458 <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" />
459 <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" />
460 <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" />
461 <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" />
464 def __init__(self, session, filterset, excludes, includes):
465 Screen.__init__(self, session)
468 self.setup_title = "AutoTimer Filters"
469 self.onChangedEntry = []
471 self.typeSelection = ConfigSelection(choices = [("title", _("in Title")), ("short", _("in Shortdescription")), ("desc", _("in Description")), ("day", _("on Weekday"))])
472 self.typeSelection.addNotifier(self.refresh, initial_call = False)
474 self.enabled = ConfigEnableDisable(default = filterset)
476 self.excludes = excludes
477 self.includes = includes
481 ConfigListScreen.__init__(self, self.list, session = session, on_change = self.changed)
484 self["key_red"] = Button(_("Cancel"))
485 self["key_green"] = Button(_("Save"))
486 self["key_yellow"] = Button(_("delete"))
487 self["key_blue"] = Button(_("New"))
490 self["actions"] = ActionMap(["SetupActions", "ColorActions"],
492 "cancel": self.cancel,
494 "yellow": self.remove,
503 for x in self.onChangedEntry:
509 def getCurrentEntry(self):
510 return self["config"].getCurrent()[0]
512 def getCurrentValue(self):
513 return str(self["config"].getCurrent()[1].getText())
515 def createSummary(self):
518 def saveCurrent(self):
519 del self.excludes[self.idx][:]
520 del self.includes[self.idx][:]
522 # Warning, accessing a ConfigListEntry directly might be considered evil!
525 for item in self["config"].getList():
527 # Skip empty entries (and those which are no filters)
528 if item[1].value == "" or idx < 2:
530 elif idx < self.lenExcludes:
531 self.excludes[self.idx].append(item[1].value.encode("UTF-8"))
533 self.includes[self.idx].append(item[1].value.encode("UTF-8"))
535 def refresh(self, value):
539 self["config"].setList(self.list)
541 def reloadList(self):
543 getConfigListEntry(_("Enable Filtering"), self.enabled),
544 getConfigListEntry(_("Filter"), self.typeSelection)
547 if self.typeSelection.value == "day":
550 # Weekdays are presented as ConfigSelection
552 getConfigListEntry(_("Exclude"), ConfigSelection(choices = weekdays, default = x))
553 for x in self.excludes[3]
555 self.lenExcludes = len(self.list)
557 getConfigListEntry(_("Include"), ConfigSelection(choices = weekdays, default = x))
558 for x in self.includes[3]
561 elif self.typeSelection.value == "title":
563 elif self.typeSelection.value == "short":
565 else: # self.typeSelection.value == "desc":
569 getConfigListEntry(_("Exclude"), ConfigText(default = x, fixed_size = False))
570 for x in self.excludes[self.idx]
572 self.lenExcludes = len(self.list)
574 getConfigListEntry(_("Include"), ConfigText(default = x, fixed_size = False))
575 for x in self.includes[self.idx]
579 idx = self["config"].getCurrentIndex()
581 if idx < self.lenExcludes:
582 self.lenExcludes -= 1
584 list = self["config"].getList()
585 list.remove(self["config"].getCurrent())
586 self["config"].setList(list)
589 self.session.openWithCallback(
592 _("Select type of Filter"),
599 def typeSelected(self, ret):
601 list = self["config"].getList()
604 pos = self.lenExcludes
605 self.lenExcludes += 1
611 if self.typeSelection.value == "day":
612 entry = getConfigListEntry(text, ConfigSelection(choices = weekdays))
614 entry = getConfigListEntry(text, ConfigText(fixed_size = False))
616 list.insert(pos, entry)
617 self["config"].setList(list)
620 if self["config"].isChanged():
621 self.session.openWithCallback(self.cancelConfirm, MessageBox, _("Really close without saving settings?"))
625 def cancelConfirm(self, ret):
638 class AutoTimerChannelEditor(Screen, ConfigListScreen):
639 """Edit allowed Channels of a AutoTimer"""
641 skin = """<screen name="AutoChannelEditor" title="Edit AutoTimer Channels" position="75,150" size="565,245">
642 <widget name="config" position="5,5" size="555,200" scrollbarMode="showOnDemand" />
643 <ePixmap position="5,205" zPosition="4" size="140,40" pixmap="skin_default/key-red.png" transparent="1" alphatest="on" />
644 <ePixmap position="145,205" zPosition="4" size="140,40" pixmap="skin_default/key-green.png" transparent="1" alphatest="on" />
645 <ePixmap position="285,205" zPosition="4" size="140,40" pixmap="skin_default/key-yellow.png" transparent="1" alphatest="on" />
646 <ePixmap position="425,205" zPosition="4" size="140,40" pixmap="skin_default/key-blue.png" transparent="1" alphatest="on" />
647 <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" />
648 <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" />
649 <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" />
650 <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" />
653 def __init__(self, session, servicerestriction, servicelist):
654 Screen.__init__(self, session)
657 self.setup_title = "AutoTimer Channels"
658 self.onChangedEntry = []
661 getConfigListEntry(_("Enable Channel Restriction"), ConfigEnableDisable(default = servicerestriction))
665 getConfigListEntry(_("Record on"), ConfigSelection(choices = [(str(x), ServiceReference(str(x)).getServiceName().replace('\xc2\x86', '').replace('\xc2\x87', ''))]))
669 ConfigListScreen.__init__(self, self.list, session = session, on_change = self.changed)
672 self["key_red"] = Button(_("Cancel"))
673 self["key_green"] = Button(_("OK"))
674 self["key_yellow"] = Button(_("delete"))
675 self["key_blue"] = Button(_("New"))
678 self["actions"] = ActionMap(["SetupActions", "ColorActions"],
680 "cancel": self.cancel,
682 "yellow": self.removeChannel,
683 "blue": self.newChannel
691 for x in self.onChangedEntry:
697 def getCurrentEntry(self):
698 return self["config"].getCurrent()[0]
700 def getCurrentValue(self):
701 return str(self["config"].getCurrent()[1].getText())
703 def createSummary(self):
706 def removeChannel(self):
707 if self["config"].getCurrentIndex() != 0:
708 list = self["config"].getList()
709 list.remove(self["config"].getCurrent())
710 self["config"].setList(list)
712 def newChannel(self):
713 self.session.openWithCallback(
714 self.finishedChannelSelection,
715 SimpleChannelSelection,
716 _("Select channel to record from")
719 def finishedChannelSelection(self, *args):
721 list = self["config"].getList()
722 sname = args[0].toString()
724 # strip all after last :
725 pos = sname.rfind(':')
727 sname = sname[:pos+1]
729 list.append(getConfigListEntry(_("Record on"), ConfigSelection(choices = [(sname, ServiceReference(args[0]).getServiceName().replace('\xc2\x86', '').replace('\xc2\x87', ''))])))
730 self["config"].setList(list)
733 if self["config"].isChanged():
734 self.session.openWithCallback(self.cancelConfirm, MessageBox, _("Really close without saving settings?"))
738 def cancelConfirm(self, ret):
743 list = self["config"].getList()
744 restriction = list.pop(0)
746 # Warning, accessing a ConfigListEntry directly might be considered evil!
748 restriction[1].value,
750 x[1].value.encode("UTF-8")