fix recursive close crashes
[enigma2.git] / lib / python / Screens / ChannelSelection.py
index 40868e870ad3f93f155943bef82f91890a7648fe..0e3ee2fcbb13c29c9b1bb900b70ca8fda48291ef 100644 (file)
@@ -12,6 +12,8 @@ from Components.NimManager import nimmanager
 from Components.ServiceName import ServiceName
 from Components.Clock import Clock
 from Components.EventInfo import EventInfo
+from Components.Input import Input
+from Screens.InputBox import InputBox
 from ServiceReference import ServiceReference
 from re import *
 from os import remove
@@ -41,9 +43,11 @@ class BouquetSelector(Screen):
                self.close(False)
 
 class ChannelContextMenu(Screen):
+       
        def __init__(self, session, csel):
                Screen.__init__(self, session)
                self.csel = csel
+               self.bsel = None
 
                self["actions"] = ActionMap(["OkCancelActions"],
                        {
@@ -52,7 +56,8 @@ class ChannelContextMenu(Screen):
                        })
                menu = [ ]
 
-               inBouquetRootList = csel.getRoot().getPath().find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK
+               current_root = csel.getRoot()
+               inBouquetRootList = current_root and current_root.getPath().find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK
                inBouquet = csel.getMutableList() is not None
                haveBouquets = csel.bouquet_root.getPath().find('FROM BOUQUET "bouquets.') != -1
 
@@ -65,16 +70,17 @@ class ChannelContextMenu(Screen):
                                                menu.append((_("add service to favourites"), self.addServiceToBouquetSelected))
                                elif haveBouquets:
                                        if not inBouquet and csel.getCurrentSelection().getPath().find("PROVIDERS") == -1:
-                                               menu.append((_("copy to favourites"), csel.copyCurrentToBouquetList))
+                                               menu.append((_("copy to favourites"), self.copyCurrentToBouquetList))
                                if inBouquet:
                                        menu.append((_("remove service"), self.removeCurrentService))
                        elif haveBouquets:
-                               menu.append((_("remove bouquet"), csel.removeBouquet))
+                               menu.append((_("remove bouquet"), self.removeBouquet))
 
                if inBouquet: # current list is editable?
                        if not csel.bouquet_mark_edit:
                                if not csel.movemode:
                                        menu.append((_("enable move mode"), self.toggleMoveMode))
+                                       menu.append((_("add bouquet..."), self.showBouquetInputBox))
                                        if not inBouquetRootList:
                                                if haveBouquets:
                                                        menu.append((_("enable bouquet edit"), self.bouquetMarkStart))
@@ -98,6 +104,13 @@ class ChannelContextMenu(Screen):
 
        def cancelClick(self):
                self.close(False)
+               
+       def showBouquetInputBox(self):
+               self.session.openWithCallback(self.bouquetInputCallback, InputBox, title=_("Please enter a name for the new bouquet"), text="bouquetname", maxSize=False, type=Input.TEXT)
+
+       def bouquetInputCallback(self, bouquet):
+               if bouquet is not None:
+                       self.csel.addBouquet(bouquet)
 
        def addServiceToBouquetSelected(self):
                bouquets = self.csel.getBouquetList()
@@ -106,13 +119,14 @@ class ChannelContextMenu(Screen):
                else:
                        cnt = len(bouquets)
                if cnt > 1: # show bouquet list
-                       self.session.openWithCallback(self.bouquetSelClosed, BouquetSelector, bouquets, self.addCurrentServiceToBouquet)
+                       self.bsel = self.session.openWithCallback(self.bouquetSelClosed, BouquetSelector, bouquets, self.addCurrentServiceToBouquet)
                elif cnt == 1: # add to only one existing bouquet
                        self.addCurrentServiceToBouquet(bouquets[0][1])
                else: #no bouquets in root.. so assume only one favourite list is used
                        self.addCurrentServiceToBouquet(self.csel.bouquet_root)
 
        def bouquetSelClosed(self, recursive):
+               self.bsel = None
                if recursive:
                        self.close(False)
 
@@ -126,7 +140,10 @@ class ChannelContextMenu(Screen):
 
        def addCurrentServiceToBouquet(self, dest):
                self.csel.addCurrentServiceToBouquet(dest)
-               self.close(True) # close bouquet selection
+               if self.bsel is not None:
+                       self.bsel.close(True)
+               else:
+                       self.close(True) # close bouquet selection
 
        def removeCurrentService(self):
                self.csel.removeCurrentService()
@@ -177,13 +194,16 @@ class ChannelSelectionEdit:
                        def __init__(self, csel, contexts = [ ], actions = { }, prio=0):
                                ActionMap.__init__(self, contexts, actions, prio)
                                self.csel = csel
+
                        def action(self, contexts, action):
                                if action == "cancel":
                                        self.csel.handleEditCancel()
+                                       return 0 # fall-trough
                                elif action == "ok":
-                                       pass # avoid typo warning...
+                                       return 0 # fall-trough
                                else:
-                                       ActionMap.action(self, contexts, action)
+                                       return ActionMap.action(self, contexts, action)
+
                self["ChannelSelectEditActions"] = ChannelSelectionEditActionMap(self, ["ChannelSelectEditActions", "OkCancelActions"],
                        {
                                "contextMenu": self.doContext,
@@ -209,6 +229,33 @@ class ChannelSelectionEdit:
                        else:
                                name += '_'
                return name
+       
+       def addBouquet(self, providerName):
+               serviceHandler = eServiceCenter.getInstance()
+               mutableBouquetList = serviceHandler.list(self.bouquet_root).startEdit()
+               if mutableBouquetList:
+                       if self.mode == MODE_TV:
+                               providerName += " (TV)"
+                               str = '1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET \"userbouquet.%s.tv\" ORDER BY bouquet'%(self.buildBouquetID(providerName))
+                       else:
+                               providerName += " (Radio)"
+                               str = '1:7:2:0:0:0:0:0:0:0:(type == 2) FROM BOUQUET \"userbouquet.%s.radio\" ORDER BY bouquet'%(self.buildBouquetID(providerName))
+                       new_bouquet_ref = eServiceReference(str)
+                       if not mutableBouquetList.addService(new_bouquet_ref):
+                               self.bouquetNumOffsetCache = { }
+                               mutableBouquetList.flushChanges()
+                               eDVBDB.getInstance().reloadBouquets()
+                               mutableBouquet = serviceHandler.list(new_bouquet_ref).startEdit()
+                               if mutableBouquet:
+                                       mutableBouquet.setListName(providerName)
+                                       mutableBouquet.flushChanges()
+                                       self.setRoot(self.getRoot())
+                               else:
+                                       print "get mutable list for new created bouquet failed"
+                       else:
+                               print "add", str, "to bouquets failed"
+               else:
+                       print "bouquetlist is not editable"
 
        def copyCurrentToBouquetList(self):
                provider = ServiceReference(self.getCurrentSelection())
@@ -257,7 +304,10 @@ class ChannelSelectionEdit:
                        if pos != -1:
                                filename = '/etc/enigma2/' + refstr[:pos] # FIXMEEE !!! HARDCODED /etc/enigma2
                self.removeCurrentService()
-               remove(filename)
+               try:
+                       remove(filename)
+               except OSError:
+                       print "error during remove of", filename
                eDVBDB.getInstance().reloadBouquets()
 
 #  multiple marked entry stuff ( edit mode, later multiepg selection )
@@ -302,7 +352,10 @@ class ChannelSelectionEdit:
                self.mutableList = None
                self.setTitle(self.saved_title)
                self.saved_title = None
-               self.servicePath = self.savedPath[:]
+               # self.servicePath is just a reference to servicePathTv or Radio...
+               # so we never ever do use the asignment operator in self.servicePath
+               del self.servicePath[:] # remove all elements
+               self.servicePath += self.savedPath # add saved elements
                del self.savedPath
                self.setRoot(self.servicePath[len(self.servicePath)-1])
 
@@ -322,13 +375,8 @@ class ChannelSelectionEdit:
                if ref.valid() and mutableList is not None:
                        if not mutableList.removeService(ref):
                                self.bouquetNumOffsetCache = { }
-                               currentIndex = self.servicelist.getCurrentIndex()
-                               self.servicelist.moveDown()
-                               if self.servicelist.getCurrentIndex() == currentIndex:
-                                       currentIndex -= 1
                                mutableList.flushChanges() #FIXME dont flush on each single removed service
                                self.setRoot(self.getRoot())
-                               self.servicelist.moveToIndex(currentIndex)
 
        def addCurrentServiceToBouquet(self, dest):
                mutableList = self.getMutableList(dest)
@@ -336,7 +384,6 @@ class ChannelSelectionEdit:
                        if not mutableList.addService(self.servicelist.getCurrent()):
                                self.bouquetNumOffsetCache = { }
                                mutableList.flushChanges()
-               self.close()
 
        def toggleMoveMode(self):
                if self.movemode:
@@ -401,7 +448,9 @@ class ChannelSelectionBase(Screen):
 
                self.servicePathTV = [ ]
                self.servicePathRadio = [ ]
-               self.servicePath = None
+               self.servicePath = [ ]
+
+               self.mode = MODE_TV
 
                self.pathChangedDisabled = False
 
@@ -424,7 +473,7 @@ class ChannelSelectionBase(Screen):
                                "7": self.keyNumberGlobal,
                                "8": self.keyNumberGlobal,
                                "9": self.keyNumberGlobal,
-                               "0": self.keyNumberGlobal
+                               "0": self.keyNumber0
                        })
 
        def appendDVBTypes(self, ref):
@@ -579,9 +628,9 @@ class ChannelSelectionBase(Screen):
                length = len(self.servicePath)
                if length:
                        current = self.servicePath[length-1]
-               self.setRoot(current, justSet)
-               if not justSet:
-                       self.setCurrentSelection(prev)
+                       self.setRoot(current, justSet)
+                       if not justSet:
+                               self.setCurrentSelection(prev)
                return prev
 
        def isBasePathEqual(self, ref):
@@ -749,6 +798,27 @@ class ChannelSelectionBase(Screen):
                        return bouquets
                return None
 
+       def keyNumber0(self, num):
+               if len(self.servicePath) > 1:
+                       self.keyGoUp()
+               else:
+                       self.keyNumberGlobal(num)
+
+       def keyGoUp(self):
+               if len(self.servicePath) > 1:
+                       if self.isBasePathEqual(self.bouquet_root):
+                               self.showFavourites()
+                       else:
+                               ref = eServiceReference('%s FROM SATELLITES ORDER BY satellitePosition'%(self.service_types))
+                               if self.isBasePathEqual(ref):
+                                       self.showSatellites()
+                               else:
+                                       ref = eServiceReference('%s FROM PROVIDERS ORDER BY name'%(self.service_types))
+                                       if self.isBasePathEqual(ref):
+                                               self.showProviders()
+                                       else:
+                                               self.showAllServices()
+
 HISTORYSIZE = 20
 
 class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelectionEPG):
@@ -761,8 +831,6 @@ class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelect
                config.tv = ConfigSubsection();
                config.tv.lastservice = configElement("config.tv.lastservice", configText, "", 0);
                config.tv.lastroot = configElement("config.tv.lastroot", configText, "", 0);
-               config.tv.prevservice = configElement("config.tv.prevservice", configText, "", 0);
-               config.tv.prevroot = configElement("config.tv.prevroot", configText, "", 0);
 
                self["actions"] = ActionMap(["OkCancelActions"],
                        {
@@ -814,18 +882,19 @@ class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelect
                        self.session.nav.playService(nref)
                self.saveRoot()
                self.saveChannel()
-               tmp=self.servicePath[:]
-               tmp.append(nref)
-               try:
-                       del self.history[self.history_pos+1:]
-               except:
-                       pass
-               self.history.append(tmp)
-               hlen = len(self.history)
-               if hlen > HISTORYSIZE:
-                       del self.history[0]
-                       hlen -= 1
-               self.history_pos = hlen-1
+               if self.servicePath is not None:
+                       tmp=self.servicePath[:]
+                       tmp.append(nref)
+                       try:
+                               del self.history[self.history_pos+1:]
+                       except:
+                               pass
+                       self.history.append(tmp)
+                       hlen = len(self.history)
+                       if hlen > HISTORYSIZE:
+                               del self.history[0]
+                               hlen -= 1
+                       self.history_pos = hlen-1
 
        def historyBack(self):
                hlen = len(self.history)
@@ -842,7 +911,8 @@ class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelect
        def setHistoryPath(self):
                path = self.history[self.history_pos][:]
                ref = path.pop()
-               self.servicePath = path
+               del self.servicePath[:]
+               self.servicePath += path
                self.saveRoot()
                plen = len(path)
                root = path[plen-1]
@@ -857,9 +927,6 @@ class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelect
                for i in self.servicePathTV:
                        path += i.toString()
                        path += ';'
-               if config.tv.prevroot.value != config.tv.lastroot.value:
-                       config.tv.prevroot.value = config.tv.lastroot.value
-                       config.tv.prevroot.save()
                if len(path) and path != config.tv.lastroot.value:
                        config.tv.lastroot.value = path
                        config.tv.lastroot.save()
@@ -897,29 +964,21 @@ class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit, ChannelSelect
                else:
                        refstr = ""
                if refstr != config.tv.lastservice.value:
-                       config.tv.prevservice.value = config.tv.lastservice.value
-                       config.tv.prevservice.save()
                        config.tv.lastservice.value = refstr
                        config.tv.lastservice.save()
 
        def recallPrevService(self):
-               if len(config.tv.prevservice.value) and len(config.tv.prevroot.value):
-                       if config.tv.lastroot.value != config.tv.prevroot.value:
-                               tmp = config.tv.lastroot.value
-                               config.tv.lastroot.value = config.tv.prevroot.value
-                               config.tv.lastroot.save()
-                               config.tv.prevroot.value = tmp
-                               config.tv.prevroot.save()
-                               self.restoreRoot()
-                       if config.tv.lastservice.value != config.tv.prevservice.value:
-                               tmp = config.tv.lastservice.value
-                               config.tv.lastservice.value = config.tv.prevservice.value
-                               config.tv.lastservice.save()
-                               config.tv.prevservice.value = tmp
-                               config.tv.prevservice.save()
-                               lastservice=eServiceReference(config.tv.lastservice.value)
-                               self.session.nav.playService(lastservice)
-                               self.setCurrentSelection(lastservice)
+               hlen = len(self.history)
+               if hlen > 1:
+                       if self.history_pos == hlen-1:
+                               tmp = self.history[self.history_pos]
+                               self.history[self.history_pos] = self.history[self.history_pos-1]
+                               self.history[self.history_pos-1] = tmp
+                       else:
+                               tmp = self.history[self.history_pos+1]
+                               self.history[self.history_pos+1] = self.history[self.history_pos]
+                               self.history[self.history_pos] = tmp
+                       self.setHistoryPath()
 
        def cancel(self):
                self.close(None)