[RecordTimer] fix repeat timer issue.
[vuplus_dvbapp] / lib / python / Screens / TimerEdit.py
1 from Components.ActionMap import ActionMap
2 from Components.Button import Button
3 from Components.config import config
4 from Components.MenuList import MenuList
5 from Components.TimerList import TimerList
6 from Components.TimerSanityCheck import TimerSanityCheck
7 from Components.UsageConfig import preferredTimerPath
8 from RecordTimer import RecordTimerEntry, parseEvent, AFTEREVENT
9 from Screen import Screen
10 from Screens.ChoiceBox import ChoiceBox
11 from Screens.MessageBox import MessageBox
12 from ServiceReference import ServiceReference
13 from TimerEntry import TimerEntry, TimerLog
14 from Tools.BoundFunction import boundFunction
15 from time import time
16 from timer import TimerEntry as RealTimerEntry
17
18 class TimerEditList(Screen):
19         EMPTY = 0
20         ENABLE = 1
21         DISABLE = 2
22         CLEANUP = 3
23         DELETE = 4
24         
25         def __init__(self, session):
26                 Screen.__init__(self, session)
27                 
28                 list = [ ]
29                 self.list = list
30                 self.fillTimerList()
31                 
32                 print "EMPTY:",self.EMPTY
33                 print "ENABLE:",self.ENABLE
34                 print "DISABLE:",self.DISABLE
35                 print "CLEANUP:",self.CLEANUP
36                 print "DELETE:",self.DELETE
37
38                 self["timerlist"] = TimerList(list)
39                 
40                 self.key_red_choice = self.EMPTY
41                 self.key_yellow_choice = self.EMPTY
42                 self.key_blue_choice = self.EMPTY
43                 
44                 self["key_red"] = Button(" ")
45                 self["key_green"] = Button(_("Add"))
46                 self["key_yellow"] = Button(" ")
47                 self["key_blue"] = Button(" ")
48
49                 print "key_red_choice:",self.key_red_choice
50
51                 self["actions"] = ActionMap(["OkCancelActions", "DirectionActions", "ShortcutActions", "TimerEditActions"], 
52                         {
53                                 "ok": self.openEdit,
54                                 "cancel": self.leave,
55                                 "green": self.addCurrentTimer,
56                                 "log": self.showLog,
57                                 "left": self.left,
58                                 "right": self.right,
59                                 "up": self.up,
60                                 "down": self.down
61                         }, -1)
62                 self.session.nav.RecordTimer.on_state_change.append(self.onStateChange)
63                 self.onShown.append(self.updateState)
64
65         def up(self):
66                 self["timerlist"].instance.moveSelection(self["timerlist"].instance.moveUp)
67                 self.updateState()
68                 
69         def down(self):
70                 self["timerlist"].instance.moveSelection(self["timerlist"].instance.moveDown)
71                 self.updateState()
72
73         def left(self):
74                 self["timerlist"].instance.moveSelection(self["timerlist"].instance.pageUp)
75                 self.updateState()
76                 
77         def right(self):
78                 self["timerlist"].instance.moveSelection(self["timerlist"].instance.pageDown)
79                 self.updateState()
80                 
81         def toggleDisabledState(self):
82                 cur=self["timerlist"].getCurrent()
83                 if cur:
84                         t = cur
85                         if t.disabled:
86                                 print "try to ENABLE timer"
87                                 t.enable()
88                                 timersanitycheck = TimerSanityCheck(self.session.nav.RecordTimer.timer_list, cur)
89                                 if not timersanitycheck.check():
90                                         t.disable()
91                                         print "Sanity check failed"
92                                         simulTimerList = timersanitycheck.getSimulTimerList()
93                                         if simulTimerList is not None:
94                                                 self.session.openWithCallback(self.finishedEdit, TimerSanityConflict, simulTimerList)
95                                 else:
96                                         print "Sanity check passed"
97                                         if timersanitycheck.doubleCheck():
98                                                 t.disable()
99                         else:
100                                 if t.isRunning():
101                                         if t.repeated:
102                                                 list = (
103                                                         (_("Stop current event but not coming events"), "stoponlycurrent"),
104                                                         (_("Stop current event and disable coming events"), "stopall"),
105                                                         (_("Don't stop current event but disable coming events"), "stoponlycoming")
106                                                 )
107                                                 self.session.openWithCallback(boundFunction(self.runningEventCallback, t), ChoiceBox, title=_("Repeating event currently recording... What do you want to do?"), list = list)
108                                 else:
109                                         t.disable()
110                         self.session.nav.RecordTimer.timeChanged(t)
111                         self.refill()
112                         self.updateState()
113
114         def runningEventCallback(self, t, result):
115                 if result is not None:
116                         if result[1] == "stoponlycurrent" or result[1] == "stopall":
117                                 t.enable()
118                                 t.processRepeated(findRunningEvent = False)
119                                 self.session.nav.RecordTimer.doActivate(t)
120                         if result[1] == "stoponlycoming" or result[1] == "stopall":
121                                 t.disable()
122                         self.session.nav.RecordTimer.timeChanged(t)
123                         self.refill()
124                         self.updateState()
125
126         def removeAction(self, descr):
127                 actions = self["actions"].actions
128                 if descr in actions:
129                         del actions[descr]
130
131         def updateState(self):
132                 cur = self["timerlist"].getCurrent()
133                 if cur:
134                         if self.key_red_choice != self.DELETE:
135                                 self["actions"].actions.update({"red":self.removeTimerQuestion})
136                                 self["key_red"].setText(_("Delete"))
137                                 self.key_red_choice = self.DELETE
138                         
139                         if cur.disabled and (self.key_yellow_choice != self.ENABLE):
140                                 self["actions"].actions.update({"yellow":self.toggleDisabledState})
141                                 self["key_yellow"].setText(_("Enable"))
142                                 self.key_yellow_choice = self.ENABLE
143                         elif cur.isRunning() and not cur.repeated and (self.key_yellow_choice != self.EMPTY):
144                                 self.removeAction("yellow")
145                                 self["key_yellow"].setText(" ")
146                                 self.key_yellow_choice = self.EMPTY
147                         elif ((not cur.isRunning())or cur.repeated ) and (not cur.disabled) and (self.key_yellow_choice != self.DISABLE):
148                                 self["actions"].actions.update({"yellow":self.toggleDisabledState})
149                                 self["key_yellow"].setText(_("Disable"))
150                                 self.key_yellow_choice = self.DISABLE
151                 else:
152                         if self.key_red_choice != self.EMPTY:
153                                 self.removeAction("red")
154                                 self["key_red"].setText(" ")
155                                 self.key_red_choice = self.EMPTY
156                         if self.key_yellow_choice != self.EMPTY:
157                                 self.removeAction("yellow")
158                                 self["key_yellow"].setText(" ")
159                                 self.key_yellow_choice = self.EMPTY
160                 
161                 showCleanup = True
162                 for x in self.list:
163                         if (not x[0].disabled) and (x[1] == True):
164                                 break
165                 else:
166                         showCleanup = False
167                 
168                 if showCleanup and (self.key_blue_choice != self.CLEANUP):
169                         self["actions"].actions.update({"blue":self.cleanupQuestion})
170                         self["key_blue"].setText(_("Cleanup"))
171                         self.key_blue_choice = self.CLEANUP
172                 elif (not showCleanup) and (self.key_blue_choice != self.EMPTY):
173                         self.removeAction("blue")
174                         self["key_blue"].setText(" ")
175                         self.key_blue_choice = self.EMPTY
176
177         def fillTimerList(self):
178                 #helper function to move finished timers to end of list
179                 def eol_compare(x, y):
180                         if x[0].state != y[0].state and x[0].state == RealTimerEntry.StateEnded or y[0].state == RealTimerEntry.StateEnded:
181                                 return cmp(x[0].state, y[0].state)
182                         return cmp(x[0].begin, y[0].begin)
183
184                 list = self.list
185                 del list[:]
186                 list.extend([(timer, False) for timer in self.session.nav.RecordTimer.timer_list])
187                 list.extend([(timer, True) for timer in self.session.nav.RecordTimer.processed_timers])
188                 if config.usage.timerlist_finished_timer_position.index: #end of list
189                         list.sort(cmp = eol_compare)
190                 else:
191                         list.sort(key = lambda x: x[0].begin)
192
193         def showLog(self):
194                 cur=self["timerlist"].getCurrent()
195                 if cur:
196                         self.session.openWithCallback(self.finishedEdit, TimerLog, cur)
197
198         def openEdit(self):
199                 cur=self["timerlist"].getCurrent()
200                 if cur:
201                         self.session.openWithCallback(self.finishedEdit, TimerEntry, cur)
202
203         def cleanupQuestion(self):
204                 self.session.openWithCallback(self.cleanupTimer, MessageBox, _("Really delete done timers?"))
205         
206         def cleanupTimer(self, delete):
207                 if delete:
208                         self.session.nav.RecordTimer.cleanup()
209                         self.refill()
210                         self.updateState()
211
212         def removeTimerQuestion(self):
213                 cur = self["timerlist"].getCurrent()
214                 if not cur:
215                         return
216
217                 self.session.openWithCallback(self.removeTimer, MessageBox, _("Do you really want to delete %s?") % (cur.name))
218
219         def removeTimer(self, result):
220                 if not result:
221                         return
222                 list = self["timerlist"]
223                 cur = list.getCurrent()
224                 if cur:
225                         timer = cur
226                         timer.afterEvent = AFTEREVENT.NONE
227                         self.session.nav.RecordTimer.removeEntry(timer)
228                         self.refill()
229                         self.updateState()
230
231         
232         def refill(self):
233                 oldsize = len(self.list)
234                 self.fillTimerList()
235                 lst = self["timerlist"]
236                 newsize = len(self.list)
237                 if oldsize and oldsize != newsize:
238                         idx = lst.getCurrentIndex()
239                         lst.entryRemoved(idx)
240                 else:
241                         lst.invalidate()
242         
243         def addCurrentTimer(self):
244                 event = None
245                 service = self.session.nav.getCurrentService()
246                 if service is not None:
247                         info = service.info()
248                         if info is not None:
249                                 event = info.getEvent(0)
250
251                 # FIXME only works if already playing a service
252                 serviceref = ServiceReference(self.session.nav.getCurrentlyPlayingServiceReference())
253                 
254                 if event is None:       
255                         data = (int(time()), int(time() + 60), "", "", None)
256                 else:
257                         data = parseEvent(event, description = False)
258
259                 self.addTimer(RecordTimerEntry(serviceref, checkOldTimers = True, dirname = preferredTimerPath(), *data))
260                 
261         def addTimer(self, timer):
262                 self.session.openWithCallback(self.finishedAdd, TimerEntry, timer)
263                         
264                 
265         def finishedEdit(self, answer):
266                 print "finished edit"
267                 
268                 if answer[0]:
269                         print "Edited timer"
270                         entry = answer[1]
271                         timersanitycheck = TimerSanityCheck(self.session.nav.RecordTimer.timer_list, entry)
272                         success = False
273                         if not timersanitycheck.check():
274                                 simulTimerList = timersanitycheck.getSimulTimerList()
275                                 if simulTimerList is not None:
276                                         for x in simulTimerList:
277                                                 if x.setAutoincreaseEnd(entry):
278                                                         self.session.nav.RecordTimer.timeChanged(x)
279                                         if not timersanitycheck.check():
280                                                 simulTimerList = timersanitycheck.getSimulTimerList()
281                                                 if simulTimerList is not None:
282                                                         self.session.openWithCallback(self.finishedEdit, TimerSanityConflict, timersanitycheck.getSimulTimerList())
283                                         else:
284                                                 success = True
285                         else:
286                                 success = True
287                         if success:
288                                 print "Sanity check passed"
289                                 self.session.nav.RecordTimer.timeChanged(entry)
290                         
291                         self.fillTimerList()
292                         self.updateState()
293                 else:
294                         print "Timeredit aborted"
295
296         def finishedAdd(self, answer):
297                 print "finished add"
298                 if answer[0]:
299                         entry = answer[1]
300                         simulTimerList = self.session.nav.RecordTimer.record(entry)
301                         if simulTimerList is not None:
302                                 for x in simulTimerList:
303                                         if x.setAutoincreaseEnd(entry):
304                                                 self.session.nav.RecordTimer.timeChanged(x)
305                                 simulTimerList = self.session.nav.RecordTimer.record(entry)
306                                 if simulTimerList is not None:
307                                         self.session.openWithCallback(self.finishSanityCorrection, TimerSanityConflict, simulTimerList)
308                         self.fillTimerList()
309                         self.updateState()
310                 else:
311                         print "Timeredit aborted"
312
313         def finishSanityCorrection(self, answer):
314                 self.finishedAdd(answer)
315
316         def leave(self):
317                 self.session.nav.RecordTimer.on_state_change.remove(self.onStateChange)
318                 self.close()
319
320         def onStateChange(self, entry):
321                 self.refill()
322                 self.updateState()
323
324 class TimerSanityConflict(Screen):
325         EMPTY = 0
326         ENABLE = 1
327         DISABLE = 2
328         EDIT = 3
329         
330         def __init__(self, session, timer):
331                 Screen.__init__(self, session)
332                 self.timer = timer
333                 print "TimerSanityConflict"
334                         
335                 self["timer1"] = TimerList(self.getTimerList(timer[0]))
336                 self.list = []
337                 self.list2 = []
338                 count = 0
339                 for x in timer:
340                         if count != 0:
341                                 self.list.append((_("Conflicting timer") + " " + str(count), x))
342                                 self.list2.append((timer[count], False))
343                         count += 1
344                 if count == 1:
345                         self.list.append((_("Channel not in services list")))
346
347                 self["list"] = MenuList(self.list)
348                 self["timer2"] = TimerList(self.list2)
349
350                 self["key_red"] = Button("Edit")
351                 self["key_green"] = Button(" ")
352                 self["key_yellow"] = Button(" ")
353                 self["key_blue"] = Button(" ")
354
355                 self.key_green_choice = self.EMPTY
356                 self.key_yellow_choice = self.EMPTY
357                 self.key_blue_choice = self.EMPTY
358
359                 self["actions"] = ActionMap(["OkCancelActions", "DirectionActions", "ShortcutActions", "TimerEditActions"], 
360                         {
361                                 "ok": self.leave_ok,
362                                 "cancel": self.leave_cancel,
363                                 "red": self.editTimer1,
364                                 "up": self.up,
365                                 "down": self.down
366                         }, -1)
367                 self.onShown.append(self.updateState)
368
369         def getTimerList(self, timer):
370                 return [(timer, False)]
371
372         def editTimer1(self):
373                 self.session.openWithCallback(self.finishedEdit, TimerEntry, self["timer1"].getCurrent())
374
375         def toggleTimer1(self):
376                 if self.timer[0].disabled:
377                         self.timer[0].disabled = False
378                 else:
379                         if not self.timer[0].isRunning():
380                                 self.timer[0].disabled = True
381                 self.finishedEdit((True, self.timer[0]))
382         
383         def editTimer2(self):
384                 self.session.openWithCallback(self.finishedEdit, TimerEntry, self["timer2"].getCurrent())
385
386         def toggleTimer2(self):
387                 x = self["list"].getSelectedIndex() + 1 # the first is the new timer so we do +1 here
388                 if self.timer[x].disabled:
389                         self.timer[x].disabled = False
390                 elif not self.timer[x].isRunning():
391                                 self.timer[x].disabled = True
392                 self.finishedEdit((True, self.timer[0]))
393         
394         def finishedEdit(self, answer):
395                 self.leave_ok()
396         
397         def leave_ok(self):
398                 self.close((True, self.timer[0]))
399         
400         def leave_cancel(self):
401                 self.close((False, self.timer[0]))
402
403         def up(self):
404                 self["list"].instance.moveSelection(self["list"].instance.moveUp)
405                 self["timer2"].moveToIndex(self["list"].getSelectedIndex())
406                 
407         def down(self):
408                 self["list"].instance.moveSelection(self["list"].instance.moveDown)
409                 self["timer2"].moveToIndex(self["list"].getSelectedIndex())
410
411         def removeAction(self, descr):
412                 actions = self["actions"].actions
413                 if descr in actions:
414                         del actions[descr]
415
416         def updateState(self):
417                 if self.timer[0] is not None:
418                         if self.timer[0].disabled and self.key_green_choice != self.ENABLE:
419                                 self["actions"].actions.update({"green":self.toggleTimer1})
420                                 self["key_green"].setText(_("Enable"))
421                                 self.key_green_choice = self.ENABLE
422                         elif self.timer[0].isRunning() and not self.timer[0].repeated and self.key_green_choice != self.EMPTY:
423                                 self.removeAction("green")
424                                 self["key_green"].setText(" ")
425                                 self.key_green_choice = self.EMPTY
426                         elif (not self.timer[0].isRunning() or self.timer[0].repeated ) and self.key_green_choice != self.DISABLE:
427                                 self["actions"].actions.update({"green":self.toggleTimer1})
428                                 self["key_green"].setText(_("Disable"))
429                                 self.key_green_choice = self.DISABLE
430                 
431                 if len(self.timer) > 1:
432                         x = self["list"].getSelectedIndex()
433                         if self.timer[x] is not None:
434                                 if self.key_yellow_choice == self.EMPTY:
435                                         self["actions"].actions.update({"yellow":self.editTimer2})
436                                         self["key_yellow"].setText(_("Edit"))
437                                         self.key_yellow_choice = self.EDIT
438                                 if self.timer[x].disabled and self.key_blue_choice != self.ENABLE:
439                                         self["actions"].actions.update({"blue":self.toggleTimer2})
440                                         self["key_blue"].setText(_("Enable"))
441                                         self.key_blue_choice = self.ENABLE
442                                 elif self.timer[x].isRunning() and not self.timer[x].repeated and self.key_blue_choice != self.EMPTY:
443                                         self.removeAction("blue")
444                                         self["key_blue"].setText(" ")
445                                         self.key_blue_choice = self.EMPTY
446                                 elif (not self.timer[x].isRunning() or self.timer[x].repeated ) and self.key_blue_choice != self.DISABLE:
447                                         self["actions"].actions.update({"blue":self.toggleTimer2})
448                                         self["key_blue"].setText(_("Disable"))
449                                         self.key_blue_choice = self.DISABLE
450                 else:
451 #FIXME.... this doesnt hide the buttons self.... just the text
452                         if self.key_yellow_choice != self.EMPTY:
453                                 self.removeAction("yellow")
454                                 self["key_yellow"].setText(" ")
455                                 self.key_yellow_choice = self.EMPTY
456                         if self.key_blue_choice != self.EMPTY:
457                                 self.removeAction("blue")
458                                 self["key_blue"].setText(" ")
459                                 self.key_blue_choice = self.EMPTY