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