use NumericalTextInput to jump to entries in ChannelSelection (jumping needs to imple...
[enigma2.git] / lib / python / Screens / ChannelSelection.py
index 1604150d34ff413aabc92eba9183a93e3eacd827..d3bf1b40ed92094ab2540fd1e75bc6a747968a8d 100644 (file)
@@ -1,12 +1,12 @@
 from Screen import Screen
 from Components.Button import Button
 from Components.ServiceList import ServiceList
 from Screen import Screen
 from Components.Button import Button
 from Components.ServiceList import ServiceList
-from Components.ActionMap import ActionMap
+from Components.ActionMap import NumberActionMap
 from EpgSelection import EPGSelection
 from enigma import eServiceReference, eEPGCache, eEPGCachePtr, eServiceCenter, eServiceCenterPtr, iMutableServiceListPtr, iStaticServiceInformationPtr, eTimer
 from Components.config import config, configElement, ConfigSubsection, configText
 from EpgSelection import EPGSelection
 from enigma import eServiceReference, eEPGCache, eEPGCachePtr, eServiceCenter, eServiceCenterPtr, iMutableServiceListPtr, iStaticServiceInformationPtr, eTimer
 from Components.config import config, configElement, ConfigSubsection, configText
-
 from Screens.FixedMenu import FixedMenu
 from Screens.FixedMenu import FixedMenu
+from Tools.NumericalTextInput import NumericalTextInput
 
 import xml.dom.minidom
 
 
 import xml.dom.minidom
 
@@ -29,8 +29,7 @@ class ChannelContextMenu(FixedMenu):
 
                menu = [ ]
 
 
                menu = [ ]
 
-               #HACK
-               inBouquetRootList = csel["list"].getRoot().toString().find('FROM BOUQUET "bouquets.') != -1
+               inBouquetRootList = csel.servicelist.getRoot().toString().find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK
                inBouquet = csel.getMutableList() is not None
 
                if not csel.bouquet_mark_edit and not csel.movemode and not inBouquetRootList:
                inBouquet = csel.getMutableList() is not None
 
                if not csel.bouquet_mark_edit and not csel.movemode and not inBouquetRootList:
@@ -60,15 +59,14 @@ class ChannelContextMenu(FixedMenu):
                serviceHandler = eServiceCenter.getInstance()
                list = serviceHandler.list(self.csel.bouquet_root)
                if not list is None:
                serviceHandler = eServiceCenter.getInstance()
                list = serviceHandler.list(self.csel.bouquet_root)
                if not list is None:
-                       while 1:
+                       while True:
                                s = list.getNext()
                                if not s.valid():
                                        break
                                if ((s.flags & eServiceReference.flagDirectory) == eServiceReference.flagDirectory):
                                        info = serviceHandler.info(s)
                                        if not info is None:
                                s = list.getNext()
                                if not s.valid():
                                        break
                                if ((s.flags & eServiceReference.flagDirectory) == eServiceReference.flagDirectory):
                                        info = serviceHandler.info(s)
                                        if not info is None:
-                                               str = info.getName(s)
-                                               bouquets.append((str, s))
+                                               bouquets.append((info.getName(s), s))
                cnt = len(bouquets)
                if cnt > 1: # show bouquet list
                        self.session.open(BouquetSelector, bouquets, self)
                cnt = len(bouquets)
                if cnt > 1: # show bouquet list
                        self.session.open(BouquetSelector, bouquets, self)
@@ -100,111 +98,40 @@ class ChannelContextMenu(FixedMenu):
        def bouquetMarkAbort(self):
                self.csel.endMarkedEdit(abort=True)
                self.close()
        def bouquetMarkAbort(self):
                self.csel.endMarkedEdit(abort=True)
                self.close()
-class ChannelSelection(Screen):
-       def lastService(self):
-               self.lastServiceTimer.stop()
-               #zap to last running tv service
-               self.setRoot(eServiceReference(config.tv.lastroot.value))
-               self.session.nav.playService(eServiceReference(config.tv.lastservice.value))
-       
-       def __init__(self, session):
-               Screen.__init__(self, session)
-
-               #config for lastservice
-               config.tv = ConfigSubsection();
-               config.tv.lastservice = configElement("config.tv.lastservice", configText, "", 0);
-               config.tv.lastroot = configElement("config.tv.lastroot", configText, "", 0);
 
 
+class ChannelSelectionEdit:
+       def __init__(self):
                self.entry_marked = False
                self.movemode = False
                self.bouquet_mark_edit = False
                self.entry_marked = False
                self.movemode = False
                self.bouquet_mark_edit = False
-               self.bouquet_root = eServiceReference('1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET "userbouquet.favourites.tv" ORDER BY bouquet')
                self.mutableList = None
                self.mutableList = None
-
                self.__marked = [ ]
 
                self.__marked = [ ]
 
-               self["key_red"] = Button("All")
-               self["key_green"] = Button("Provider")
-               self["key_yellow"] = Button("Satellite")
-               self["key_blue"] = Button("Favourites")
-               
-               self["list"] = ServiceList()
-
-               if config.tv.lastroot.value == "":
-                       self["list"].setRoot(eServiceReference("""1:0:1:0:0:0:0:0:0:0:(type == 1)"""))
-               #self["okbutton"] = Button("ok", [self.channelSelected])
-
-               self.lastServiceTimer = eTimer()
-               self.lastServiceTimer.timeout.get().append(self.lastService)
-               self.lastServiceTimer.start(100)
-
-               class ChannelActionMap(ActionMap):
-                       def action(self, contexts, action):
-                               if action[:7] == "bouquet":
-                                       l = self.csel
-                                       list = l["list"]
-                                       if action.find("FROM BOUQUET") != -1:
-                                               l.setRoot(eServiceReference("1:7:1:0:0:0:0:0:0:0:" + action[8:]))
-                                       else:
-                                               l.setRoot(eServiceReference("1:0:1:0:0:0:0:0:0:0:" + action[8:]))
-                               else:
-                                       if action == "cancel":
-                                               l = self.csel
-                                               if l.movemode: #movemode active?
-                                                       l.channelSelected() # unmark
-                                                       l.toggleMoveMode() # disable move mode
-                                               elif l.bouquet_mark_edit:
-                                                       l.endMarkedEdit(True) # abort edit mode
-                                       ActionMap.action(self, contexts, action)
-
-               self["actions"] = ChannelActionMap(["ChannelSelectActions", "OkCancelActions", "ContextMenuActions"], 
-                       {
-                               "cancel": self.close,
-                               "ok": self.channelSelected,
-                               "mark": self.doMark,
-                               "contextMenu": self.doContext,
-                               "showFavourites": self.showFavourites,
-                   "showEPGList": self.showEPGList
-                       })
-               self["actions"].csel = self
-
-       def showEPGList(self):
-               ref=self["list"].getCurrent()
-               ptr=eEPGCache.getInstance()
-               if ptr.startTimeQuery(ref) != -1:
-                       self.session.open(EPGSelection, ref)
-               else:
-                       print 'no epg for service', ref.toString()
-
        def getMutableList(self, root=eServiceReference()):
                if not self.mutableList is None:
                        return self.mutableList
                serviceHandler = eServiceCenter.getInstance()
                if not root.valid():
        def getMutableList(self, root=eServiceReference()):
                if not self.mutableList is None:
                        return self.mutableList
                serviceHandler = eServiceCenter.getInstance()
                if not root.valid():
-                       root=self["list"].getRoot()
+                       root=self.servicelist.getRoot()
                list = serviceHandler.list(root)
                list = serviceHandler.list(root)
-               mutableList = None
                if list is not None:
                if list is not None:
-                       mutableList = list.startEdit()
-               return mutableList
+                       return list.startEdit()
+               return None
 
 #  multiple marked entry stuff ( edit mode, later multiepg selection )
        def startMarkedEdit(self):
                self.mutableList = self.getMutableList()
 
 #  multiple marked entry stuff ( edit mode, later multiepg selection )
        def startMarkedEdit(self):
                self.mutableList = self.getMutableList()
-               l = self["list"]
                # add all services from the current list to internal marked set in listboxservicecontent
                # add all services from the current list to internal marked set in listboxservicecontent
-               self.bouquetRoot = l.getRoot()
+               self.bouquetRoot = self.servicelist.getRoot()
                self.clearMarks() # this clears the internal marked set in the listboxservicecontent
                self.bouquet_mark_edit = True
                self.clearMarks() # this clears the internal marked set in the listboxservicecontent
                self.bouquet_mark_edit = True
-               self.__marked = l.getRootServices()
+               self.__marked = self.servicelist.getRootServices()
                for x in self.__marked:
                for x in self.__marked:
-                       l.addMarked(eServiceReference(x))
+                       self.servicelist.addMarked(eServiceReference(x))
 
        def endMarkedEdit(self, abort):
 
        def endMarkedEdit(self, abort):
-               l = self["list"]
                if not abort and self.mutableList is not None:
                if not abort and self.mutableList is not None:
-                       new_marked = set(l.getMarked())
+                       new_marked = set(self.servicelist.getMarked())
                        old_marked = set(self.__marked)
                        removed = old_marked - new_marked
                        added = new_marked - old_marked
                        old_marked = set(self.__marked)
                        removed = old_marked - new_marked
                        added = new_marked - old_marked
@@ -226,89 +153,222 @@ class ChannelSelection(Screen):
                self.mutableList = None
 
        def clearMarks(self):
                self.mutableList = None
 
        def clearMarks(self):
-               self["list"].clearMarks()
+               self.servicelist.clearMarks()
 
        def doMark(self):
 
        def doMark(self):
-               ref = self["list"].getCurrent()
-               if self["list"].isMarked(ref):
-                       self["list"].removeMarked(ref)
+               ref = self.servicelist.getCurrent()
+               if self.servicelist.isMarked(ref):
+                       self.servicelist.removeMarked(ref)
                else:
                else:
-                       self["list"].addMarked(ref)
+                       self.servicelist.addMarked(ref)
 
        def removeCurrentService(self):
 
        def removeCurrentService(self):
-               l = self["list"]
-               ref = l.getCurrent()
+               ref = self.servicelist.getCurrent()
                mutableList = self.getMutableList()
                if ref.valid() and mutableList is not None:
                mutableList = self.getMutableList()
                if ref.valid() and mutableList is not None:
-                       if mutableList.removeService(ref) == 0:
+                       if not mutableList.removeService(ref):
                                mutableList.flushChanges() #FIXME dont flush on each single removed service
                                mutableList.flushChanges() #FIXME dont flush on each single removed service
-                               self.setRoot(l.getRoot())
+                               self.setRoot(self.servicelist.getRoot())
 
        def addCurrentServiceToBouquet(self, dest):
                mutableList = self.getMutableList(dest)
                if not mutableList is None:
 
        def addCurrentServiceToBouquet(self, dest):
                mutableList = self.getMutableList(dest)
                if not mutableList is None:
-                       if mutableList.addService(self["list"].getCurrent()) == 0:
+                       if not mutableList.addService(self.servicelist.getCurrent()):
                                mutableList.flushChanges()
                self.close()
 
                                mutableList.flushChanges()
                self.close()
 
-       def setRoot(self, root):
-               if not self.movemode: # dont change root when movemode is enabled
-                       list = self["list"]
-
-                       #HACK
-                       inBouquetRootList = root.toString().find('FROM BOUQUET "bouquets.') != -1
-
-                       if not inBouquetRootList and ((root.flags & eServiceReference.flagDirectory) == eServiceReference.flagDirectory):
-                               list.setMode(list.MODE_FAVOURITES)
-                       else:
-                               list.setMode(list.MODE_NORMAL)
-                       list.setRoot(root)
-
-       def channelSelected(self):
-               ref = self["list"].getCurrent()
+       def toggleMoveMode(self):
                if self.movemode:
                        if self.entry_marked:
                if self.movemode:
                        if self.entry_marked:
-                               self["list"].setCurrentMarked(False)
-                               self.entry_marked = False
-                       else:
-                               self["list"].setCurrentMarked(True)
-                               self.entry_marked = True
-               elif (ref.flags & 7) == 7:
-                       self.setRoot(ref)
+                               self.toggleMoveMarked() # unmark current entry
+                       self.movemode = False
+                       self.mutableList.flushChanges() # FIXME add check if changes was made
+                       self.mutableList = None
+               else:
+                       self.mutableList = self.getMutableList()
+                       self.movemode = True
+
+       def handleEditCancel(self):
+               if self.movemode: #movemode active?
+                       self.channelSelected() # unmark
+                       self.toggleMoveMode() # disable move mode
                elif self.bouquet_mark_edit:
                elif self.bouquet_mark_edit:
-                       self.doMark()
+                       self.endMarkedEdit(True) # abort edit mode
+
+       def toggleMoveMarked(self):
+               if self.entry_marked:
+                       self.servicelist.setCurrentMarked(False)
+                       self.entry_marked = False
                else:
                else:
-                       self.session.nav.playService(ref)
-                       self.saveChannel()
-                       self.close()
+                       self.servicelist.setCurrentMarked(True)
+                       self.entry_marked = True
 
 
-       #called from infoBar
-       def zap(self):
-               self.session.nav.playService(self["list"].getCurrent())
-               self.saveChannel()
+       def doContext(self):
+               self.session.open(ChannelContextMenu, self)
+
+class ChannelSelectionBase(Screen):
+       def __init__(self, session):
+               Screen.__init__(self, session)
+
+               self.bouquet_root = eServiceReference('1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET "bouquets.tv" ORDER BY bouquet')
+               #self.bouquet_root = eServiceReference('1:7:1:0:0:0:0:0:0:0:(type == 1) FROM BOUQUET "userbouquet.favourites.tv" ORDER BY bouquet')
+
+               self["key_red"] = Button("All")
+               #self["key_green"] = Button("Provider")
+               #self["key_yellow"] = Button("Satellite")
+               self["key_green"] = Button("")
+               self["key_yellow"] = Button("")
+               self["key_blue"] = Button("Favourites")
+
+               self["list"] = ServiceList()
+               self.servicelist = self["list"]
+
+               #self["okbutton"] = Button("ok", [self.channelSelected])
+               
+               self.numericalTextInput = NumericalTextInput()
+               
+               self.lastService = None
+
+               self.lastServiceTimer = eTimer()
+               self.lastServiceTimer.timeout.get().append(self.lastService)
+               self.lastServiceTimer.start(100)
+
+       def getBouquetNumOffset(self, bouquet):
+               if self.bouquet_root.toString().find('FROM BOUQUET "bouquets.') == -1: #FIXME HACK
+                       return 0
+               offsetCount = 0
+               serviceHandler = eServiceCenter.getInstance()
+               bouquetlist = serviceHandler.list(self.bouquet_root)
+               if not bouquetlist is None:
+                       while True:
+                               bouquetIterator = bouquetlist.getNext()
+                               if not bouquetIterator.valid() or bouquetIterator == bouquet: #end of list or bouquet found
+                                       break
+                               if ((bouquetIterator.flags & eServiceReference.flagDirectory) != eServiceReference.flagDirectory):
+                                       continue
+                               servicelist = serviceHandler.list(bouquetIterator)
+                               if not servicelist is None:
+                                       while True:
+                                               serviceIterator = servicelist.getNext()
+                                               if not serviceIterator.valid(): #check if end of list
+                                                       break
+                                               if serviceIterator.flags: #playable services have no flags
+                                                       continue
+                                               offsetCount += 1
+               return offsetCount
+
+       def setRootBase(self, root):
+               inBouquetRootList = root.toString().find('FROM BOUQUET "bouquets.') != -1 #FIXME HACK
+               if not inBouquetRootList and ((root.flags & eServiceReference.flagDirectory) == eServiceReference.flagDirectory):
+                       self.servicelist.setMode(ServiceList.MODE_FAVOURITES)
+                       self.servicelist.setNumberOffset(self.getBouquetNumOffset(root))
+               else:
+                       self.servicelist.setMode(ServiceList.MODE_NORMAL)
+               self.servicelist.setRoot(root)
 
        def moveUp(self):
 
        def moveUp(self):
-               self["list"].moveUp()
+               self.servicelist.moveUp()
 
        def moveDown(self):
 
        def moveDown(self):
-               self["list"].moveDown()
+               self.servicelist.moveDown()
 
 
-       def doContext(self):
-               self.session.open(ChannelContextMenu, self)
+       def showFavourites(self):
+               self.setRoot(self.bouquet_root)
 
 
-       def toggleMoveMode(self):
+       def keyNumberGlobal(self, number):
+               print "You pressed number " + str(number)
+               print "You would go to character " + str(self.numericalTextInput.getKey(number))
+               pass
+
+       def enterBouquet(self, action):
+               if action[:7] == "bouquet":
+                       if action.find("FROM BOUQUET") != -1:
+                               self.setRoot(eServiceReference("1:7:1:0:0:0:0:0:0:0:" + action[8:]))
+                       else:
+                               self.setRoot(eServiceReference("1:0:1:0:0:0:0:0:0:0:" + action[8:]))
+                       return True
+               return False
+
+       def getRoot(self):
+               return self.servicelist.getRoot()
+
+       def getCurrentSelection(self):
+               return self.servicelist.getCurrent()
+
+       def setCurrentSelection(self, service):
+               self.servicelist.setCurrent(service)
+
+       def cancel(self):
+               self.close(None)
+
+class ChannelSelection(ChannelSelectionBase, ChannelSelectionEdit):
+       def __init__(self, session):
+               ChannelSelectionBase.__init__(self,session)
+               ChannelSelectionEdit.__init__(self)
+
+               #config for lastservice
+               config.tv = ConfigSubsection();
+               config.tv.lastservice = configElement("config.tv.lastservice", configText, "", 0);
+               config.tv.lastroot = configElement("config.tv.lastroot", configText, "", 0);
+
+               if config.tv.lastroot.value == "":
+                       self.servicelist.setRoot(eServiceReference("""1:0:1:0:0:0:0:0:0:0:(type == 1)"""))
+
+               class ChannelActionMap(NumberActionMap):
+                       def action(self, contexts, action):
+                               if not self.csel.enterBouquet(action):
+                                       if action == "cancel":
+                                               self.csel.handleEditCancel()
+                                       NumberActionMap.action(self, contexts, action)
+               self["actions"] = ChannelActionMap(["ChannelSelectActions", "OkCancelActions", "ContextMenuActions"],
+                       {
+                               "cancel": self.cancel,
+                               "ok": self.channelSelected,
+                               "mark": self.doMark,
+                               "contextMenu": self.doContext,
+                               "showFavourites": self.showFavourites,
+                               "showEPGList": self.showEPGList,
+                               "1": self.keyNumberGlobal,
+               "2": self.keyNumberGlobal,
+               "3": self.keyNumberGlobal,
+               "4": self.keyNumberGlobal,
+               "5": self.keyNumberGlobal,
+               "6": self.keyNumberGlobal,
+               "7": self.keyNumberGlobal,
+               "8": self.keyNumberGlobal,
+               "9": self.keyNumberGlobal,
+               "0": self.keyNumberGlobal
+                       })
+               self["actions"].csel = self
+
+       def showEPGList(self):
+               ref=self.servicelist.getCurrent()
+               ptr=eEPGCache.getInstance()
+               if ptr.startTimeQuery(ref) != -1:
+                       self.session.open(EPGSelection, ref)
+               else:
+                       print 'no epg for service', ref.toString()
+
+       def channelSelected(self):
+               ref = self.servicelist.getCurrent()
                if self.movemode:
                if self.movemode:
-                       if self.entry_marked:
-                               self.channelSelected() # unmark current entry
-                       self.movemode = False
-                       self.mutableList.flushChanges() # FIXME add check if changes was made
-                       self.mutableList = None
+                       self.toggleMoveMarked()
+               elif (ref.flags & 7) == 7:
+                       self.setRoot(ref)
+               elif self.bouquet_mark_edit:
+                       self.doMark()
                else:
                else:
-                       self.mutableList = self.getMutableList()
-                       self.movemode = True
+                       self.zap()
+                       self.close(ref)
 
 
-       def showFavourites(self):
-               self.setRoot(self.bouquet_root)
+       def setRoot(self, root):
+               if not self.movemode:
+                       self.setRootBase(root)
+
+       #called from infoBar and channelSelected
+       def zap(self):
+               self.session.nav.playService(self.servicelist.getCurrent())
+               self.saveChannel()
 
        def saveRoot(self, root):
                if root is not None:
 
        def saveRoot(self, root):
                if root is not None:
@@ -323,3 +383,49 @@ class ChannelSelection(Screen):
                        refstr = ""
                config.tv.lastservice.value = refstr
                config.tv.lastservice.save()
                        refstr = ""
                config.tv.lastservice.value = refstr
                config.tv.lastservice.save()
+
+       def lastService(self):
+               self.lastServiceTimer.stop()
+               #zap to last running tv service
+               self.setRoot(eServiceReference(config.tv.lastroot.value))
+               self.session.nav.playService(eServiceReference(config.tv.lastservice.value))
+
+class SimpleChannelSelection(ChannelSelectionBase):
+       def __init__(self, session, title):
+               ChannelSelectionBase.__init__(self, session)
+               self.title = title
+               self.onShown.append(self.onExecCallback)
+
+               class ChannelActionMap(ActionMap):
+                       def action(self, contexts, action):
+                               if not self.csel.enterBouquet(action):
+                                       ActionMap.action(self, contexts, action)
+               self["actions"] = ChannelActionMap(["ChannelSelectActions", "OkCancelActions", "ContextMenuActions"],
+                       {
+                               "cancel": self.cancel,
+                               "ok": self.channelSelected,
+                               "showFavourites": self.showFavourites,
+                               "1": self.keyNumberGlobal,
+               "2": self.keyNumberGlobal,
+               "3": self.keyNumberGlobal,
+               "4": self.keyNumberGlobal,
+               "5": self.keyNumberGlobal,
+               "6": self.keyNumberGlobal,
+               "7": self.keyNumberGlobal,
+               "8": self.keyNumberGlobal,
+               "9": self.keyNumberGlobal,
+               "0": self.keyNumberGlobal
+                       })
+               self["actions"].csel = self
+
+       def onExecCallback(self):
+               print "onExecCallback"
+               self.session.currentDialog.instance.setTitle(self.title)
+
+       def channelSelected(self): # just return selected service
+               ref = self.servicelist.getCurrent()
+               self.close(ref)
+
+       def setRoot(self, root):
+               self.setRootBase(root)
+