def VirtualKeyBoardEntryComponent(keys, selectedKey, shiftMode=False): key_bg = LoadPixmap(cached=True, path=resolveFilename(SCOPE_ACTIVE_SKIN, "buttons/vkey_bg.png")) key_bg_width = key_bg.size().width() if shiftMode: key_images = KEY_IMAGES_SHIFT else: key_images = KEY_IMAGES res = [ (keys) ] x = 0 count = 0 for count, key in enumerate(keys): width = None png = key_images.get(key, None) if png: pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_ACTIVE_SKIN, png)) width = pixmap.size().width() res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=pixmap)) else: width = key_bg_width res.extend(( MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=key_bg), MultiContentEntryText(pos=(x, 0), size=(width, 45), font=0, text=key.encode("utf-8"), flags=RT_HALIGN_CENTER | RT_VALIGN_CENTER) )) if selectedKey == count: key_sel = LoadPixmap(cached=True, path=resolveFilename(SCOPE_ACTIVE_SKIN, "buttons/vkey_sel.png")) width = key_sel.size().width() res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=key_sel)) if width is not None: x += width else: x += 45 return res
def ChoiceEntryComponent(self, data): width = self['list'].instance.size().width() height = self['list'].l.getItemSize().height() self.ml.l.setFont(0, gFont(mp_globals.font, height - 4 * mp_globals.sizefactor)) res = [data[1]] plugin_path = mp_globals.pluginPath skin_path = mp_globals.pluginPath + mp_globals.skinsPath key = "key_" + data[0] + ".png" path = "%s/%s/images/%s" % (skin_path, config.mediaportal.skin.value, key) if not fileExists(path): path = "%s/%s/images/%s" % (skin_path, mp_globals.skinFallback, key) if not fileExists(path): path = resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/buttons/" + key) png = LoadPixmap(path) if png is not None: global pwidth pwidth = png.size().width() pheight = png.size().height() vpos = round(float((height-pheight)/2)) res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, 5, vpos, pwidth, pheight, png)) if data[1][0] == "--": res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 0, 1000, height, 0, RT_HALIGN_LEFT | RT_VALIGN_CENTER, "-"*200)) else: res.append((eListboxPythonMultiContent.TYPE_TEXT, pwidth+15, 0, 1000, height, 0, RT_HALIGN_LEFT | RT_VALIGN_CENTER, data[1][0])) return res
def VirtualKeyBoardEntryComponent(keys, selectedKey, shiftMode=False): key_bg = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_bg.png")) key_bg_width = key_bg.size().width() if shiftMode: key_images = KEY_IMAGES_SHIFT else: key_images = KEY_IMAGES res = [(keys)] x = 0 count = 0 for count, key in enumerate(keys): width = None png = key_images.get(key, None) if png: pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, png)) width = pixmap.size().width() res.append( MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=pixmap)) else: width = key_bg_width res.extend((MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=key_bg), MultiContentEntryText(pos=(x, 0), size=(width, 45), font=0, text=key.encode("utf-8"), flags=RT_HALIGN_CENTER | RT_VALIGN_CENTER))) if selectedKey == count: key_sel = LoadPixmap(cached=True, path=resolveFilename( SCOPE_CURRENT_SKIN, "skin_default/vkey_sel.png")) width = key_sel.size().width() res.append( MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=key_sel)) if width is not None: x += width else: x += 45 return res
def ChoiceEntryComponent(key=None, text=["--"]): res = [text] if text[0] == "--": x, y, w, h = skin.parameters.get( "ChoicelistDash", (skin.applySkinFactor(0), skin.applySkinFactor(2), skin.applySkinFactor(800), skin.applySkinFactor(25))) res.append((eListboxPythonMultiContent.TYPE_TEXT, x, y, w, h, 0, RT_HALIGN_LEFT, "-" * 200)) else: x, y, w, h = skin.parameters.get( "ChoicelistName", (skin.applySkinFactor(45), skin.applySkinFactor(2), skin.applySkinFactor(800), skin.applySkinFactor(25))) res.append((eListboxPythonMultiContent.TYPE_TEXT, x, y, w, h, 0, RT_HALIGN_LEFT, text[0])) if key: if key == "expandable": pngfile = resolveFilename(SCOPE_ACTIVE_SKIN, "icons/expandable.png") elif key == "expanded": pngfile = resolveFilename(SCOPE_ACTIVE_SKIN, "icons/expanded.png") elif key == "verticalline": pngfile = resolveFilename(SCOPE_ACTIVE_SKIN, "icons/verticalline.png") elif key == "bullet": pngfile = resolveFilename(SCOPE_ACTIVE_SKIN, "icons/bullet.png") else: pngfile = resolveFilename(SCOPE_ACTIVE_SKIN, "buttons/key_%s.png" % key) if fileExists(pngfile): png = LoadPixmap(pngfile) x, y, w, h = skin.parameters.get( "ChoicelistIcon", (skin.applySkinFactor(5), skin.applySkinFactor(0), png.size().width(), png.size().height())) res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, x, y, w, h, png)) return res
def downloadPicCallback(self, page=""): picture = LoadPixmap(self.pic) size = picture.size() width = size.width() height = size.height() self["pic"].instance.setPixmap(picture) self["pic"].instance.resize(eSize(width, height)) left = int((550 / 2) - (width / 2)) top = int((450 / 2) - (height / 2)) self["pic"].moveTo(left, top, 1) self["pic"].startMoving() self["pic"].show() self.working = False
def VirtualKeyBoardEntryComponent(keys, selectedKey, shiftMode = False): global PLUGIN_PATH key_backspace = LoadPixmap(cached=True, path='%s/img/vkey_backspace.png' % PLUGIN_PATH) key_bg = LoadPixmap(cached=True, path='%s/img/vkey_bg.png' % PLUGIN_PATH) key_clr = LoadPixmap(cached=True, path='%s/img/vkey_clr.png' % PLUGIN_PATH) key_esc = LoadPixmap(cached=True, path='%s/img/vkey_esc.png' % PLUGIN_PATH) key_ok = LoadPixmap(cached=True, path='%s/img/vkey_ok.png' % PLUGIN_PATH) key_sel = LoadPixmap(cached=True, path='%s/img/vkey_sel.png' % PLUGIN_PATH) key_shift = LoadPixmap(cached=True, path='%s/img/vkey_shift.png' % PLUGIN_PATH) key_shift_sel = LoadPixmap(cached=True, path='%s/img/vkey_shift_sel.png' % PLUGIN_PATH) key_space = LoadPixmap(cached=True, path='%s/img/vkey_space.png' % PLUGIN_PATH) res = [keys] x = 0 count = 0 if shiftMode: shiftkey_png = key_shift_sel else: shiftkey_png = key_shift for key in keys: width = None if key == 'EXIT': width = key_esc.size().width() res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=key_esc)) elif key == 'BACKSPACE': width = key_backspace.size().width() res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=key_backspace)) elif key == 'CLEAR': width = key_clr.size().width() res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=key_clr)) elif key == 'SHIFT': width = shiftkey_png.size().width() res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=shiftkey_png)) elif key == 'SPACE': width = key_space.size().width() res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=key_space)) elif key == 'OK': width = key_ok.size().width() res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=key_ok)) else: width = key_bg.size().width() res.extend((MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=key_bg), MultiContentEntryText(pos=(x, 0), size=(width, 45), font=0, text=key.encode('utf-8'), flags=RT_HALIGN_CENTER | RT_VALIGN_CENTER))) if selectedKey == count: width = key_sel.size().width() res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=key_sel)) if width is not None: x += width else: x += 45 count += 1 return res
def ChoiceEntryComponent(self, data): width = self['list'].instance.size().width() height = self['list'].l.getItemSize().height() self.ml.l.setFont( 0, gFont(mp_globals.font, height - 4 * mp_globals.sizefactor)) res = [data[1]] skin_path = mp_globals.pluginPath + mp_globals.skinsPath key = "key_" + data[0] + ".png" path = "%s/%s/images/%s" % (skin_path, mp_globals.currentskin, key) if not fileExists(path): path = "%s/%s/images/%s" % (skin_path, mp_globals.skinFallback, key) if not fileExists(path): path = resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/buttons/" + key) png = LoadPixmap(path) if png is not None: global pwidth pwidth = png.size().width() pheight = png.size().height() vpos = round(float((height - pheight) / 2)) res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, 5, vpos, pwidth, pheight, png)) if data[1][0] == "--": res.append( (eListboxPythonMultiContent.TYPE_TEXT, 0, 0, 1000, height, 0, RT_HALIGN_LEFT | RT_VALIGN_CENTER, "-" * 200)) else: res.append( (eListboxPythonMultiContent.TYPE_TEXT, pwidth + 15, 0, 1000, height, 0, RT_HALIGN_LEFT | RT_VALIGN_CENTER, data[1][0])) return res
class VirtualKeyBoard(Screen): skin = '''<screen name="KodiLiteVKskin" position="center,center" size="1200,560" zPosition="99" title="Virtual keyboard"> <ePixmap pixmap="skin_default/vkey_text.png" position="300,245" zPosition="-4" size="542,52" alphatest="on" /> <widget source="country" render="Pixmap" position="40,400" size="60,40" alphatest="on" borderWidth="2" borderColor="yellow" > <convert type="ValueToPixmap">LanguageCode</convert> </widget> <eLabel text="language" position="40,350" size="100,35" font="Regular;21" foregroundColor="white" backgroundColor="yellow" /> <widget name="header" position="10,10" size="500,20" font="Regular;20" transparent="1" noWrap="1" /> <widget name="text" position="302,250" size="536,46" font="Regular;42" transparent="1" noWrap="1" halign="right" /> <widget name="list" position="300,300" size="680,240" selectionDisabled="1" transparent="1" /> <eLabel text="Press blue for suggestion" position="900,10" size="300,35" font="Regular;21" foregroundColor="blue" backgroundColor="white" /> <widget name="suggestlist" position="900,50" size="300,200" selectionDisabled="1" transparent="1" /> <eLabel text="Press red for history" position="50,10" size="300,35" font="Regular;21" foregroundColor="red" backgroundColor="white" /> <widget name="historylist" position="50,50" size="200,200" selectionDisabled="1" transparent="1" /> </screen>''' def __init__(self, session, title='', text=''): Screen.__init__(self, session) self.skinName = 'KodiLiteVKskin' self.keys_list = [] self.session = session self.shiftkeys_list = [] self.lang = language.getLanguage() self.nextLang = None self.shiftMode = False self.text = text self.selectedKey = 0 self['suggestlist'] = MenuList([]) self['historylist'] = MenuList([]) self.key_bg = LoadPixmap(path=resolveFilename( SCOPE_CURRENT_SKIN, 'skin_default/vkey_bg.png')) self.key_sel = LoadPixmap(path=resolveFilename( SCOPE_CURRENT_SKIN, 'skin_default/vkey_sel.png')) self.key_backspace = LoadPixmap(path=resolveFilename( SCOPE_CURRENT_SKIN, 'skin_default/vkey_backspace.png')) self.key_all = LoadPixmap(path=resolveFilename( SCOPE_CURRENT_SKIN, 'skin_default/vkey_all.png')) self.key_clr = LoadPixmap(path=resolveFilename( SCOPE_CURRENT_SKIN, 'skin_default/vkey_clr.png')) self.key_esc = LoadPixmap(path=resolveFilename( SCOPE_CURRENT_SKIN, 'skin_default/vkey_esc.png')) self.key_ok = LoadPixmap(path=resolveFilename( SCOPE_CURRENT_SKIN, 'skin_default/vkey_ok.png')) self.key_shift = LoadPixmap(path=resolveFilename( SCOPE_CURRENT_SKIN, 'skin_default/vkey_shift.png')) self.key_shift_sel = LoadPixmap(path=resolveFilename( SCOPE_CURRENT_SKIN, 'skin_default/vkey_shift_sel.png')) self.key_space = LoadPixmap(path=resolveFilename( SCOPE_CURRENT_SKIN, 'skin_default/vkey_space.png')) self.key_left = LoadPixmap(path=resolveFilename( SCOPE_CURRENT_SKIN, 'skin_default/vkey_left.png')) self.key_right = LoadPixmap(path=resolveFilename( SCOPE_CURRENT_SKIN, 'skin_default/vkey_right.png')) self.keyImages = { 'BACKSPACE': self.key_backspace, 'ALL': self.key_all, 'EXIT': self.key_esc, 'OK': self.key_ok, 'SHIFT': self.key_shift, 'SPACE': self.key_space, 'LEFT': self.key_left, 'RIGHT': self.key_right } self.keyImagesShift = { 'BACKSPACE': self.key_backspace, 'CLEAR': self.key_clr, 'EXIT': self.key_esc, 'OK': self.key_ok, 'SHIFT': self.key_shift_sel, 'SPACE': self.key_space, 'LEFT': self.key_left, 'RIGHT': self.key_right } self['country'] = StaticText('') self['header'] = Label('') self['text'] = Label(self.text) self['list'] = VirtualKeyBoardList([]) self['actions'] = ActionMap( [ 'ColorActions', 'OkCancelActions', 'WizardActions', 'KeyboardInputActions', 'InputBoxActions', 'InputAsciiActions', "MenuActions" ], { 'gotAsciiCode': self.keyGotAscii, 'ok': self.okClicked, 'cancel': self.exit, 'left': self.left, 'right': self.right, 'up': self.up, 'down': self.down, 'red': self.history, 'green': self.ok, 'blue': self.suggest, 'menu': self.showmenu, 'yellow': self.switchLang, 'deleteBackward': self.backClicked, '0': self.insertspace, 'back': self.exit }, -2) self.setLang() self.displayhistory() self.onExecBegin.append(self.setKeyboardModeAscii) self.onLayoutFinish.append(self.buildVirtualKeyBoard) self.onLayoutFinish.append(self.getsuggestion) self.currentlist = 'list' return def showmenu(self): nlines = [] nlines.append( (str("Clear search history"), str("Clear search history"))) self.session.openWithCallback(self.choicesback, ChoiceBox, _('select action'), nlines) def choicesback(self, select): if select: if select[0] == 'Clear search history': self.historydel() def historydel(self): self.session.openWithCallback( self.delhx, MessageBox, _('All search history items will be deleted,are you sure?'), MessageBox.TYPE_YESNO) def delhx(self, answer): if answer: hfile = '/etc/history' try: os.remove(hfile) self['historylist'].setList([]) except: print 'failed to delete history' def suggest(self): debug = True self['suggestlist'].selectionEnabled(1) self['historylist'].selectionEnabled(0) self['list'].selectionEnabled(0) self.currentlist = 'suggestlist' def history(self): self['suggestlist'].selectionEnabled(0) self['historylist'].selectionEnabled(1) self['list'].selectionEnabled(0) self.currentlist = 'historylist' def displayhistory(self): hfile = '/etc/history' if not os.path.exists(hfile): return lines = open(hfile).readlines() list1 = [] for line in lines: list1.append(line.strip()) self['historylist'].setList(list1) def getsuggestion(self): word = self['text'].getText() if word.strip() == '': return lang = self.lang.split('_')[0] self.suggestions = GoogleSuggestions(self.suggestcallback, lang) self.suggestions.getSuggestions(word, hl=lang) def suggestcallback(self, data): if data is None: return else: list1 = data print 'list1', list1 self['suggestlist'].setList(list1) return return def suggestback(self, select): print '143', select if select: self['text'].setText(str(select)) def switchLang(self): self.lang = self.nextLang self.setLang() self.buildVirtualKeyBoard() def setLang(self): if self.lang == 'de_DE': self.keys_list = [[ u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE' ], [ u'q', u'w', u'e', u'r', u't', u'z', u'u', u'i', u'o', u'p', u'\xfc', u'+' ], [ u'a', u's', u'd', u'f', u'g', u'h', u'j', u'k', u'l', u'\xf6', u'\xe4', u'#' ], [ u'<', u'y', u'x', u'c', u'v', u'b', u'n', u'm', u',', '.', u'-', u'CLEAR' ], [u'SHIFT', u'SPACE', u'@', u'\xdf', u'OK']] self.shiftkeys_list = [[ u'EXIT', u'!', u'"', u'\xa7', u'$', u'%', u'&', u'/', u'(', u')', u'=', u'BACKSPACE' ], [ u'Q', u'W', u'E', u'R', u'T', u'Z', u'U', u'I', u'O', u'P', u'\xdc', u'*' ], [ u'A', u'S', u'D', u'F', u'G', u'H', u'J', u'K', u'L', u'\xd6', u'\xc4', u"'" ], [ u'>', u'Y', u'X', u'C', u'V', u'B', u'N', u'M', u';', u':', u'_', u'CLEAR' ], [u'SHIFT', u'SPACE', u'?', u'\\', u'OK']] self.nextLang = 'ar_AE' elif self.lang == 'ar_AE': self.keys_list = [[ u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE' ], [ u'\u0636', u'\u0635', u'\u062b', u'\u0642', u'\u0641', u'\u063a', u'\u0639', u'\u0647', u'\u062e', u'\u062d', u'\u062c', u'\u062f' ], [ u'\u0634', u'\u0633', u'\u064a', u'\u0628', u'\u0644', u'\u0627', u'\u062a', u'\u0646', u'\u0645', u'\u0643', u'\u0637', u'\u0630' ], [ u'\u0626', u'\u0621', u'\u0624', u'\u0631', u'\u0644\u0627', u'\u0649', u'\u0629', u'\u0648', u'\u0632', '\xd8\xb8', u'#', u'CLEAR' ], [ u'SHIFT', u'SPACE', u'-', u'@', u'.', u'\u0644\u0622', u'\u0622', u'\u0644\u0623', u'\u0644\u0625', u'\u0625', u'\u0623', u'OK' ]] self.shiftkeys_list = [[ u'EXIT', u'!', u'"', u'\xa7', u'$', u'^', u'<', u'>', u'(', u')', u'=', u'BACKSPACE' ], [ u'\u064e', u'\u064b', u'\u064f', u'\u064c', u'%', u'\u060c', u'\u2018', u'\xf7', u'\xd7', u'\u061b', u'<', u'>' ], [ u'\u0650', u'\u064d', u']', u'[', u'*', u'+', u'\u0640', u'\u060c', u'/', u':', u'~', u"'" ], [ u'\u0652', u'}', u'{', u'-', u'/', u'\u2019', u',', u'.', u'\u061f', u':', u'_', u'CLEAR' ], [ u'SHIFT', u'SPACE', u'?', u'\\', u'=', u'\u0651', u'~', u'OK' ]] self.nextLang = 'es_ES' elif self.lang == 'es_ES': self.keys_list = [[ u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE' ], [ u'q', u'w', u'e', u'r', u't', u'z', u'u', u'i', u'o', u'p', u'\xfa', u'+' ], [ u'a', u's', u'd', u'f', u'g', u'h', u'j', u'k', u'l', u'\xf3', u'\xe1', u'#' ], [ u'<', u'y', u'x', u'c', u'v', u'b', u'n', u'm', u',', '.', u'-', u'ALL' ], [ u'SHIFT', u'SPACE', u'@', u'\u0141', u'\u0155', u'\xe9', u'\u010d', u'\xed', u'\u011b', u'\u0144', u'\u0148', u'OK' ]] self.shiftkeys_list = [[ u'EXIT', u'!', u'"', u'\xa7', u'$', u'%', u'&', u'/', u'(', u')', u'=', u'BACKSPACE' ], [ u'Q', u'W', u'E', u'R', u'T', u'Z', u'U', u'I', u'O', u'P', u'\xda', u'*' ], [ u'A', u'S', u'D', u'F', u'G', u'H', u'J', u'K', u'L', u'\xd3', u'\xc1', u"'" ], [ u'>', u'Y', u'X', u'C', u'V', u'B', u'N', u'M', u';', u':', u'_', u'CLEAR' ], [ u'SHIFT', u'SPACE', u'?', u'\\', u'\u0154', u'\xc9', u'\u010c', u'\xcd', u'\u011a', u'\u0143', u'\u0147', u'OK' ]] self.nextLang = 'fi_FI' elif self.lang == 'fi_FI': self.keys_list = [[ u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE' ], [ u'q', u'w', u'e', u'r', u't', u'z', u'u', u'i', u'o', u'p', u'\xe9', u'+' ], [ u'a', u's', u'd', u'f', u'g', u'h', u'j', u'k', u'l', u'\xf6', u'\xe4', u'#' ], [ u'<', u'y', u'x', u'c', u'v', u'b', u'n', u'm', u',', '.', u'-', u'CLEAR' ], [ u'SHIFT', u'SPACE', u'@', u'\xdf', u'\u013a', u'OK' ]] self.shiftkeys_list = [[ u'EXIT', u'!', u'"', u'\xa7', u'$', u'%', u'&', u'/', u'(', u')', u'=', u'BACKSPACE' ], [ u'Q', u'W', u'E', u'R', u'T', u'Z', u'U', u'I', u'O', u'P', u'\xc9', u'*' ], [ u'A', u'S', u'D', u'F', u'G', u'H', u'J', u'K', u'L', u'\xd6', u'\xc4', u"'" ], [ u'>', u'Y', u'X', u'C', u'V', u'B', u'N', u'M', u';', u':', u'_', u'CLEAR' ], [ u'SHIFT', u'SPACE', u'?', u'\\', u'\u0139', u'OK' ]] self.nextLang = 'sv_SE' elif self.lang == 'sv_SE': self.keys_list = [[ u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE' ], [ u'q', u'w', u'e', u'r', u't', u'z', u'u', u'i', u'o', u'p', u'\xe9', u'+' ], [ u'a', u's', u'd', u'f', u'g', u'h', u'j', u'k', u'l', u'\xf6', u'\xe4', u'#' ], [ u'<', u'y', u'x', u'c', u'v', u'b', u'n', u'm', u',', '.', u'-', u'CLEAR' ], [ u'SHIFT', u'SPACE', u'@', u'\xdf', u'\u013a', u'OK' ]] self.shiftkeys_list = [[ u'EXIT', u'!', u'"', u'\xa7', u'$', u'%', u'&', u'/', u'(', u')', u'=', u'BACKSPACE' ], [ u'Q', u'W', u'E', u'R', u'T', u'Z', u'U', u'I', u'O', u'P', u'\xc9', u'*' ], [ u'A', u'S', u'D', u'F', u'G', u'H', u'J', u'K', u'L', u'\xd6', u'\xc4', u"'" ], [ u'>', u'Y', u'X', u'C', u'V', u'B', u'N', u'M', u';', u':', u'_', u'CLEAR' ], [ u'SHIFT', u'SPACE', u'?', u'\\', u'\u0139', u'OK' ]] self.nextLang = 'sk_SK' elif self.lang == 'sk_SK': self.keys_list = [[ u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE' ], [ u'q', u'w', u'e', u'r', u't', u'z', u'u', u'i', u'o', u'p', u'\xfa', u'+' ], [ u'a', u's', u'd', u'f', u'g', u'h', u'j', u'k', u'l', u'\u013e', u'@', u'#' ], [ u'<', u'y', u'x', u'c', u'v', u'b', u'n', u'm', u',', '.', u'-', u'CLEAR' ], [ u'SHIFT', u'SPACE', u'\u0161', u'\u010d', u'\u017e', u'\xfd', u'\xe1', u'\xed', u'\xe9', u'OK' ]] self.shiftkeys_list = [[ u'EXIT', u'!', u'"', u'\xa7', u'$', u'%', u'&', u'/', u'(', u')', u'=', u'BACKSPACE' ], [ u'Q', u'W', u'E', u'R', u'T', u'Z', u'U', u'I', u'O', u'P', u'\u0165', u'*' ], [ u'A', u'S', u'D', u'F', u'G', u'H', u'J', u'K', u'L', u'\u0148', u'\u010f', u"'" ], [ u'\xc1', u'\xc9', u'\u010e', u'\xcd', u'\xdd', u'\xd3', u'\xda', u'\u017d', u'\u0160', u'\u010c', u'\u0164', u'\u0147' ], [ u'>', u'Y', u'X', u'C', u'V', u'B', u'N', u'M', u';', u':', u'_', u'CLEAR' ], [ u'SHIFT', u'SPACE', u'?', u'\\', u'\xe4', u'\xf6', u'\xfc', u'\xf4', u'\u0155', u'\u013a', u'OK' ]] self.nextLang = 'cs_CZ' elif self.lang == 'cs_CZ': self.keys_list = [[ u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE' ], [ u'q', u'w', u'e', u'r', u't', u'z', u'u', u'i', u'o', u'p', u'\xfa', u'+' ], [ u'a', u's', u'd', u'f', u'g', u'h', u'j', u'k', u'l', u'\u016f', u'@', u'#' ], [ u'<', u'y', u'x', u'c', u'v', u'b', u'n', u'm', u',', '.', u'-', u'CLEAR' ], [ u'SHIFT', u'SPACE', u'\u011b', u'\u0161', u'\u010d', u'\u0159', u'\u017e', u'\xfd', u'\xe1', u'\xed', u'\xe9', u'OK' ]] self.shiftkeys_list = [[ u'EXIT', u'!', u'"', u'\xa7', u'$', u'%', u'&', u'/', u'(', u')', u'=', u'BACKSPACE' ], [ u'Q', u'W', u'E', u'R', u'T', u'Z', u'U', u'I', u'O', u'P', u'\u0165', u'*' ], [ u'A', u'S', u'D', u'F', u'G', u'H', u'J', u'K', u'L', u'\u0148', u'\u010f', u"'" ], [ u'>', u'Y', u'X', u'C', u'V', u'B', u'N', u'M', u';', u':', u'_', u'CLEAR' ], [ u'SHIFT', u'SPACE', u'?', u'\\', u'\u010c', u'\u0158', u'\u0160', u'\u017d', u'\xda', u'\xc1', u'\xc9', u'OK' ]] self.nextLang = 'el_GR' elif self.lang == 'el_GR': self.keys_list = [[ u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE' ], [ u'=', u'\u03c2', u'\u03b5', u'\u03c1', u'\u03c4', u'\u03c5', u'\u03b8', u'\u03b9', u'\u03bf', u'\u03c0', u'[', u']' ], [ u'\u03b1', u'\u03c3', u'\u03b4', u'\u03c6', u'\u03b3', u'\u03b7', u'\u03be', u'\u03ba', u'\u03bb', u';', u"'", u'-' ], [ u'\\', u'\u03b6', u'\u03c7', u'\u03c8', u'\u03c9', u'\u03b2', u'\u03bd', u'\u03bc', u',', '.', u'/', u'CLEAR' ], [ u'SHIFT', u'SPACE', u'\u03ac', u'\u03ad', u'\u03ae', u'\u03af', u'\u03cc', u'\u03cd', u'\u03ce', u'\u03ca', u'\u03cb', u'OK' ]] self.shiftkeys_list = [[ u'EXIT', u'!', u'@', u'#', u'$', u'%', u'^', u'&', u'*', u'(', u')', u'BACKSPACE' ], [ u'+', u'\u20ac', u'\u0395', u'\u03a1', u'\u03a4', u'\u03a5', u'\u0398', u'\u0399', u'\u039f', u'\u03a0', u'{', u'}' ], [ u'\u0391', u'\u03a3', u'\u0394', u'\u03a6', u'\u0393', u'\u0397', u'\u039e', u'\u039a', u'\u039b', u':', u'"', u'_' ], [ u'|', u'\u0396', u'\u03a7', u'\u03a8', u'\u03a9', u'\u0392', u'\u039d', u'\u039c', u'<', u'>', u'?', u'CLEAR' ], [ u'SHIFT', u'SPACE', u'\u0386', u'\u0388', u'\u0389', u'\u038a', u'\u038c', u'\u038e', u'\u038f', u'\u03aa', u'\u03ab', u'OK' ]] self.nextLang = 'pl_PL' elif self.lang == 'pl_PL': self.keys_list = [[ u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE' ], [ u'q', u'w', u'e', u'r', u't', u'y', u'u', u'i', u'o', u'p', u'-', u'[' ], [ u'a', u's', u'd', u'f', u'g', u'h', u'j', u'k', u'l', u';', u"'", u'\\' ], [ u'<', u'z', u'x', u'c', u'v', u'b', u'n', u'm', u',', '.', u'/', u'CLEAR' ], [ u'SHIFT', u'SPACE', u'\u0105', u'\u0107', u'\u0119', u'\u0142', u'\u0144', u'\xf3', u'\u015b', u'\u017a', u'\u017c', u'OK' ]] self.shiftkeys_list = [[ u'EXIT', u'!', u'@', u'#', u'$', u'%', u'^', u'&', u'(', u')', u'=', u'BACKSPACE' ], [ u'Q', u'W', u'E', u'R', u'T', u'Y', u'U', u'I', u'O', u'P', u'*', u']' ], [ u'A', u'S', u'D', u'F', u'G', u'H', u'J', u'K', u'L', u'?', u'"', u'|' ], [ u'>', u'Z', u'X', u'C', u'V', u'B', u'N', u'M', u';', u':', u'_', u'CLEAR' ], [ u'SHIFT', u'SPACE', u'\u0104', u'\u0106', u'\u0118', u'\u0141', u'\u0143', u'\xd3', u'\u015a', u'\u0179', u'\u017b', u'OK' ]] self.nextLang = 'en_EN' else: self.keys_list = [[ u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE' ], [ u'q', u'w', u'e', u'r', u't', u'y', u'u', u'i', u'o', u'p', u'-', u'[' ], [ u'a', u's', u'd', u'f', u'g', u'h', u'j', u'k', u'l', u';', u"'", u'\\' ], [ u'<', u'z', u'x', u'c', u'v', u'b', u'n', u'm', u',', '.', u'/', u'CLEAR' ], [u'SHIFT', u'SPACE', u'OK', u'*']] self.shiftkeys_list = [[ u'EXIT', u'!', u'@', u'#', u'$', u'%', u'^', u'&', u'(', u')', u'=', u'BACKSPACE' ], [ u'Q', u'W', u'E', u'R', u'T', u'Y', u'U', u'I', u'O', u'P', u'+', u']' ], [ u'A', u'S', u'D', u'F', u'G', u'H', u'J', u'K', u'L', u'?', u'"', u'|' ], [ u'>', u'Z', u'X', u'C', u'V', u'B', u'N', u'M', u';', u':', u'_', u'CLEAR' ], [u'SHIFT', u'SPACE', u'OK', u'~']] self.lang = 'en_EN' self.nextLang = 'de_DE' self['country'].setText(self.lang) self.max_key = 47 + len(self.keys_list[4]) def virtualKeyBoardEntryComponent(self, keys): w, h = parameters.get('VirtualKeyboard', (45, 45)) key_bg_width = self.key_bg and self.key_bg.size().width() or w key_images = self.shiftMode and self.keyImagesShift or self.keyImages res = [keys] text = [] x = 0 for key in keys: png = key_images.get(key, None) if png: width = png.size().width() res.append( MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, h), png=png)) else: width = key_bg_width res.append( MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, h), png=self.key_bg)) text.append( MultiContentEntryText(pos=(x, 0), size=(width, h), font=0, text=key.encode('utf-8'), flags=RT_HALIGN_CENTER | RT_VALIGN_CENTER)) x += width return res + text def buildVirtualKeyBoard(self, selectedkey=None): self.previousSelectedKey = None self.list = [] for keys in self.shiftMode and self.shiftkeys_list or self.keys_list: self.list.append(self.virtualKeyBoardEntryComponent(keys)) self.markSelectedKey() return def markSelectedKey(self): w, h = parameters.get('VirtualKeyboard', (45, 45)) if self.previousSelectedKey is not None: self.list[self.previousSelectedKey / 12] = self.list[self.previousSelectedKey / 12][:-1] width = self.key_sel.size().width() x = self.list[self.selectedKey / 12][self.selectedKey % 12 + 1][1] self.list[self.selectedKey / 12].append( MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, h), png=self.key_sel)) self.previousSelectedKey = self.selectedKey self['list'].setList(self.list) return def backClicked(self): if self.currentlist == 'list': self.text = self['text'].getText()[:-1] self['text'].setText(self.text) self.getsuggestion() def insertspace(self): print 'self.currentlist', self.currentlist if self.currentlist == 'suggestlist': return elif self.currentlist == 'historylist': return else: if self.shiftMode: list = self.shiftkeys_list else: list = self.keys_list selectedKey = self.selectedKey text = None for x in list: if selectedKey < 12: if selectedKey < len(x): text = x[selectedKey] break else: selectedKey -= 12 if text is None: return text = 'SPACE' if text == 'EXIT': self.close(None) elif text == 'BACKSPACE': self.text = self['text'].getText()[:-1] self['text'].setText(self.text) elif text == 'CLEAR': self.text = '' self['text'].setText(self.text) elif text == 'SHIFT': if self.shiftMode: self.shiftMode = False else: self.shiftMode = True self.buildVirtualKeyBoard(self.selectedKey) elif text == 'SPACE': self.text += ' ' self['text'].setText(self.text) elif text == 'OK': self.close(self['text'].getText()) else: self.text = self['text'].getText() self.text += text self['text'].setText(self.text) self.getsuggestion() return return def okClicked(self): print 'self.currentlist', self.currentlist if self.currentlist == 'suggestlist': txt = str(self['suggestlist'].l.getCurrentSelection()) print 'txt', txt self['text'].setText(txt) self.exit() self.currentlist == 'list' return elif self.currentlist == 'historylist': txt = str(self['historylist'].l.getCurrentSelection()) self['text'].setText(txt) self.exit() self.currentlist == 'list' return else: if self.shiftMode: list = self.shiftkeys_list else: list = self.keys_list selectedKey = self.selectedKey text = None for x in list: if selectedKey < 12: if selectedKey < len(x): text = x[selectedKey] break else: selectedKey -= 12 if text is None: return text = text.encode('UTF-8') if text == 'EXIT': self.close(None) elif text == 'BACKSPACE': self.text = self['text'].getText()[:-1] self['text'].setText(self.text) elif text == 'CLEAR': self.text = '' self['text'].setText(self.text) elif text == 'SHIFT': if self.shiftMode: self.shiftMode = False else: self.shiftMode = True self.buildVirtualKeyBoard(self.selectedKey) elif text == 'SPACE': self.text += ' ' self['text'].setText(self.text) elif text == 'OK': self.close(self['text'].getText()) else: self.text = self['text'].getText() self.text += text self['text'].setText(self.text) self.getsuggestion() return return def ok(self): txt = str(self['text'].getText()) writetohistory(txt) self.close(txt) def exit(self): debug = True if self.currentlist == 'suggestlist': self['suggestlist'].selectionEnabled(0) self['historylist'].selectionEnabled(0) self['list'].selectionEnabled(1) self.currentlist = 'list' return elif self.currentlist == 'historylist': self['suggestlist'].selectionEnabled(0) self['historylist'].selectionEnabled(0) self['list'].selectionEnabled(1) self.currentlist = 'list' return else: try: self.suggestions = None self.suggestcallback = None except: pass self.close(None) return return def left(self): self.selectedKey -= 1 if self.selectedKey == -1: self.selectedKey = 11 elif self.selectedKey == 11: self.selectedKey = 23 elif self.selectedKey == 23: self.selectedKey = 35 elif self.selectedKey == 35: self.selectedKey = 47 elif self.selectedKey == 47: self.selectedKey = self.max_key self.showActiveKey() def right(self): self.selectedKey += 1 if self.selectedKey == 12: self.selectedKey = 0 elif self.selectedKey == 24: self.selectedKey = 12 elif self.selectedKey == 36: self.selectedKey = 24 elif self.selectedKey == 48: self.selectedKey = 36 elif self.selectedKey > self.max_key: self.selectedKey = 48 self.showActiveKey() def up(self): if self.currentlist == 'suggestlist': self['suggestlist'].up() print 'suggestlist' return if self.currentlist == 'historylist': self['historylist'].up() return self.selectedKey -= 12 if self.selectedKey < 0 and self.selectedKey > self.max_key - 60: self.selectedKey += 48 elif self.selectedKey < 0: self.selectedKey += 60 self.showActiveKey() def down(self): if self.currentlist == 'suggestlist': self['suggestlist'].down() print 'suggestlist' return if self.currentlist == 'historylist': self['historylist'].down() return self.selectedKey += 12 if self.selectedKey > self.max_key and self.selectedKey > 59: self.selectedKey -= 60 elif self.selectedKey > self.max_key: self.selectedKey -= 48 self.showActiveKey() def showActiveKey(self): self.buildVirtualKeyBoard(self.selectedKey) def inShiftKeyList(self, key): for KeyList in self.shiftkeys_list: for char in KeyList: if char == key: return True return False def keyGotAscii(self): char = str(unichr(getPrevAsciiCode()).encode('utf-8')) if self.inShiftKeyList(char): self.shiftMode = True list = self.shiftkeys_list else: self.shiftMode = False list = self.keys_list if char == ' ': char = 'SPACE' selkey = 0 for keylist in list: for key in keylist: if key == char: self.selectedKey = selkey self.okClicked() self.showActiveKey() return selkey += 1
class VirtualKeyBoard(Screen): def __init__(self, session, title="", **kwargs): Screen.__init__(self, session) self.setTitle(_("Virtual KeyBoard")) self.keys_list = [] self.shiftkeys_list = [] self.lang = language.getLanguage() self.nextLang = None self.shiftMode = False self.selectedKey = 0 self.smsChar = None self.sms = NumericalTextInput(self.smsOK) self.key_bg = LoadPixmap( path=resolveFilename(SCOPE_ACTIVE_SKIN, "buttons/vkey_bg.png")) self.key_sel = LoadPixmap( path=resolveFilename(SCOPE_ACTIVE_SKIN, "buttons/vkey_sel.png")) self.key_backspace = LoadPixmap(path=resolveFilename( SCOPE_ACTIVE_SKIN, "buttons/vkey_backspace.png")) self.key_all = LoadPixmap( path=resolveFilename(SCOPE_ACTIVE_SKIN, "buttons/vkey_all.png")) self.key_clr = LoadPixmap( path=resolveFilename(SCOPE_ACTIVE_SKIN, "buttons/vkey_clr.png")) self.key_esc = LoadPixmap( path=resolveFilename(SCOPE_ACTIVE_SKIN, "buttons/vkey_esc.png")) self.key_ok = LoadPixmap( path=resolveFilename(SCOPE_ACTIVE_SKIN, "buttons/vkey_ok.png")) self.key_shift = LoadPixmap( path=resolveFilename(SCOPE_ACTIVE_SKIN, "buttons/vkey_shift.png")) self.key_shift_sel = LoadPixmap(path=resolveFilename( SCOPE_ACTIVE_SKIN, "buttons/vkey_shift_sel.png")) self.key_space = LoadPixmap( path=resolveFilename(SCOPE_ACTIVE_SKIN, "buttons/vkey_space.png")) self.key_left = LoadPixmap( path=resolveFilename(SCOPE_ACTIVE_SKIN, "buttons/vkey_left.png")) self.key_right = LoadPixmap( path=resolveFilename(SCOPE_ACTIVE_SKIN, "buttons/vkey_right.png")) self.keyImages = { "BACKSPACE": self.key_backspace, "ALL": self.key_all, "EXIT": self.key_esc, "OK": self.key_ok, "SHIFT": self.key_shift, "SPACE": self.key_space, "LEFT": self.key_left, "RIGHT": self.key_right } self.keyImagesShift = { "BACKSPACE": self.key_backspace, "CLEAR": self.key_clr, "EXIT": self.key_esc, "OK": self.key_ok, "SHIFT": self.key_shift_sel, "SPACE": self.key_space, "LEFT": self.key_left, "RIGHT": self.key_right } self["country"] = StaticText("") self["header"] = Label() self["text"] = Input(currPos=len( kwargs.get("text", "").decode("utf-8", 'ignore')), allMarked=False, **kwargs) self["list"] = VirtualKeyBoardList([]) self["actions"] = NumberActionMap( [ "OkCancelActions", "WizardActions", "ColorActions", "KeyboardInputActions", "InputBoxActions", "InputAsciiActions" ], { "gotAsciiCode": self.keyGotAscii, "ok": self.okClicked, "OKLong": self.okLongClicked, "cancel": self.exit, "left": self.left, "right": self.right, "up": self.up, "down": self.down, "red": self.exit, "green": self.ok, "yellow": self.switchLang, "blue": self.shiftClicked, "deleteBackward": self.backClicked, "deleteForward": self.forwardClicked, "back": self.exit, "pageUp": self.cursorRight, "pageDown": self.cursorLeft, "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, }, -2) self.setLang() self.onExecBegin.append(self.setKeyboardModeAscii) self.onLayoutFinish.append(self.buildVirtualKeyBoard) self.onClose.append(self.__onClose) def __onClose(self): self.sms.timer.stop() def switchLang(self): self.lang = self.nextLang self.setLang() self.buildVirtualKeyBoard() def setLang(self): if self.lang == 'de_DE': self.keys_list = [[ u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE" ], [ u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"ü", u"+" ], [ u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ö", u"ä", u"#" ], [ u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL" ], [ u"SHIFT", u"SPACE", u"@", u"ß", u"OK", u"LEFT", u"RIGHT" ]] self.shiftkeys_list = [[ u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE" ], [ u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"Ü", u"*" ], [ u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"Ö", u"Ä", u"'" ], [ u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR" ], [ u"SHIFT", u"SPACE", u"?", u"\\", u"OK", u"LEFT", u"RIGHT" ]] self.nextLang = 'es_ES' elif self.lang == 'es_ES': self.keys_list = [[ u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE" ], [ u"q", u"w", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"¡", u"'" ], [ u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ñ", u"ç", u"+" ], [ u"<", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL" ], [ u"SHIFT", u"SPACE", u"@", u"á", u"é", u"í", u"ó", u"ú", u"ü", u"º", u"ª", u"OK" ]] self.shiftkeys_list = [[ u"EXIT", u"!", u'"', u"·", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE" ], [ u"Q", u"W", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"¿", u"?" ], [ u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"Ñ", u"Ç", u"*" ], [ u">", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR" ], [ u"SHIFT", u"SPACE", u"€", u"Á", u"É", u"Í", u"Ó", u"Ú", u"Ü", u"[", u"]", u"OK" ]] self.nextLang = 'fi_FI' elif self.lang == 'fi_FI': self.keys_list = [[ u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE" ], [ u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"é", u"+" ], [ u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ö", u"ä", u"#" ], [ u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL" ], [ u"SHIFT", u"SPACE", u"@", u"ß", u"ĺ", u"OK", u"LEFT", u"RIGHT" ]] self.shiftkeys_list = [[ u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE" ], [ u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"É", u"*" ], [ u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"Ö", u"Ä", u"'" ], [ u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR" ], [ u"SHIFT", u"SPACE", u"?", u"\\", u"Ĺ", u"OK", u"LEFT", u"RIGHT" ]] self.nextLang = 'ru_RU' elif self.lang == 'ru_RU': self.keys_list = [[ u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE" ], [ u"а", u"б", u"в", u"г", u"д", u"е", u"ё", u"ж", u"з", u"и", u"й", u"+" ], [ u"к", u"л", u"м", u"н", u"о", u"п", u"р", u"с", u"т", u"у", u"ф", u"#" ], [ u"<", u"х", u"ц", u"ч", u"ш", u"щ", u"ъ", u"ы", u",", u".", u"-", u"ALL" ], [ u"SHIFT", u"SPACE", u"@", u"ь", u"э", u"ю", u"я", u"OK", u"LEFT", u"RIGHT" ]] self.shiftkeys_list = [[ u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE" ], [ u"А", u"Б", u"В", u"Г", u"Д", u"Е", u"Ё", u"Ж", u"З", u"И", u"Й", u"*" ], [ u"К", u"Л", u"М", u"Н", u"О", u"П", u"Р", u"С", u"Т", u"У", u"Ф", u"'" ], [ u">", u"Х", u"Ц", u"Ч", u"Ш", u"Щ", u"Ъ", u"Ы", u";", u":", u"_", u"CLEAR" ], [ u"SHIFT", u"SPACE", u"?", u"\\", u"Ь", u"Э", u"Ю", u"Я", u"OK", u"LEFT", u"RIGHT" ]] self.nextLang = 'sv_SE' elif self.lang == 'sv_SE': self.keys_list = [[ u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE" ], [ u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"é", u"+" ], [ u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ö", u"ä", u"#" ], [ u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL" ], [ u"SHIFT", u"SPACE", u"@", u"ß", u"ĺ", u"OK", u"LEFT", u"RIGHT" ]] self.shiftkeys_list = [[ u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE" ], [ u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"É", u"*" ], [ u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"Ö", u"Ä", u"'" ], [ u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR" ], [ u"SHIFT", u"SPACE", u"?", u"\\", u"Ĺ", u"OK", u"LEFT", u"RIGHT" ]] self.nextLang = 'ar_AE' elif self.lang == 'ar_AE': self.keys_list = [[ u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE" ], [ u"ض", u"ص", u"ث", u"ق", u"ف", u"غ", u"ع", u"ه", u"خ", u"ح", u"ج", u"د" ], [ u"ش", u"س", u"ي", u"ب", u"ل", u"ا", u"ت", u"ن", u"م", u"ك", u"ط", u"#" ], [ u"ئ", u"ء", u"ؤ", u"ر", u"لا", u"ى", u"ة", u"و", u"ز", "ظ", u"ذ", u"CLEAR" ], [ u"SHIFT", u"SPACE", u"+", u"-", u"*", u"/", u".", u",", u"@", u"%", u"&", u"OK" ]] self.shiftkeys_list = [[ u"EXIT", u"!", u'"', u"§", u"$", u"^", u"<", u">", u"(", u")", u"=", u"BACKSPACE" ], [ u"َ", u"ً", u"ُ", u"ٌ", u"لإ", u"إ", u"‘", u"÷", u"×", u"؛", u"<", u">" ], [ u"ِ", u"ٍ", u"]", u"[", u"لأ", u"أ", u"ـ", u"،", u"/", u":", u"~", u"'" ], [ u"ْ", u"}", u"{", u"لآ", u"آ", u"’", u",", u".", u"؟", u":", u"_", u"CLEAR" ], [ u"SHIFT", u"SPACE", u"?", u"\\", u"=", u"ّ", u"~", u"OK" ]] self.nextLang = 'sk_SK' elif self.lang == 'sk_SK': self.keys_list = [[ u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE" ], [ u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"ú", u"+" ], [ u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ľ", u"@", u"#" ], [ u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL" ], [ u"SHIFT", u"SPACE", u"š", u"č", u"ž", u"ý", u"á", u"í", u"é", u"OK", u"LEFT", u"RIGHT" ]] self.shiftkeys_list = [[ u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE" ], [ u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"ť", u"*" ], [ u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"ň", u"ď", u"'" ], [ u"Á", u"É", u"Ď", u"Í", u"Ý", u"Ó", u"Ú", u"Ž", u"Š", u"Č", u"Ť", u"Ň" ], [ u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR" ], [ u"SHIFT", u"SPACE", u"?", u"\\", u"ä", u"ö", u"ü", u"ô", u"ŕ", u"ĺ", u"OK" ]] self.nextLang = 'cs_CZ' elif self.lang == 'cs_CZ': self.keys_list = [[ u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE" ], [ u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"ú", u"+" ], [ u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ů", u"@", u"#" ], [ u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL" ], [ u"SHIFT", u"SPACE", u"ě", u"š", u"č", u"ř", u"ž", u"ý", u"á", u"í", u"é", u"OK" ]] self.shiftkeys_list = [[ u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE" ], [ u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"ť", u"*" ], [ u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"ň", u"ď", u"'" ], [ u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR" ], [ u"SHIFT", u"SPACE", u"?", u"\\", u"Č", u"Ř", u"Š", u"Ž", u"Ú", u"Á", u"É", u"OK" ]] self.nextLang = 'el_GR' elif self.lang == 'el_GR': self.keys_list = [[ u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE" ], [ u"=", u"ς", u"ε", u"ρ", u"τ", u"υ", u"θ", u"ι", u"ο", u"π", u"[", u"]" ], [ u"α", u"σ", u"δ", u"φ", u"γ", u"η", u"ξ", u"κ", u"λ", u";", u"'", u"-" ], [ u"\\", u"ζ", u"χ", u"ψ", u"ω", u"β", u"ν", u"μ", u",", ".", u"/", u"ALL" ], [ u"SHIFT", u"SPACE", u"ά", u"έ", u"ή", u"ί", u"ό", u"ύ", u"ώ", u"ϊ", u"ϋ", u"OK" ]] self.shiftkeys_list = [[ u"EXIT", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"*", u"(", u")", u"BACKSPACE" ], [ u"+", u"€", u"Ε", u"Ρ", u"Τ", u"Υ", u"Θ", u"Ι", u"Ο", u"Π", u"{", u"}" ], [ u"Α", u"Σ", u"Δ", u"Φ", u"Γ", u"Η", u"Ξ", u"Κ", u"Λ", u":", u'"', u"_" ], [ u"|", u"Ζ", u"Χ", u"Ψ", u"Ω", u"Β", u"Ν", u"Μ", u"<", u">", u"?", u"CLEAR" ], [ u"SHIFT", u"SPACE", u"Ά", u"Έ", u"Ή", u"Ί", u"Ό", u"Ύ", u"Ώ", u"Ϊ", u"Ϋ", u"OK" ]] self.nextLang = 'pl_PL' elif self.lang == 'pl_PL': self.keys_list = [[ u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE" ], [ u"q", u"w", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"-", u"[" ], [ u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u";", u"'", u"\\" ], [ u"<", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"/", u"ALL" ], [ u"SHIFT", u"SPACE", u"ą", u"ć", u"ę", u"ł", u"ń", u"ó", u"ś", u"ź", u"ż", u"OK" ]] self.shiftkeys_list = [[ u"EXIT", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"(", u")", u"=", u"BACKSPACE" ], [ u"Q", u"W", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"*", u"]" ], [ u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"?", u'"', u"|" ], [ u">", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR" ], [ u"SHIFT", u"SPACE", u"Ą", u"Ć", u"Ę", u"Ł", u"Ń", u"Ó", u"Ś", u"Ź", u"Ż", u"OK" ]] self.nextLang = 'en_US' else: self.keys_list = [[ u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE" ], [ u"q", u"w", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"-", u"[" ], [ u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u";", u"'", u"\\" ], [ u"<", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"/", u"ALL" ], [ u"SHIFT", u"SPACE", u"OK", u"LEFT", u"RIGHT", u"*" ]] self.shiftkeys_list = [[ u"EXIT", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"(", u")", u"=", u"BACKSPACE" ], [ u"Q", u"W", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"+", u"]" ], [ u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"?", u'"', u"|" ], [ u">", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR" ], [ u"SHIFT", u"SPACE", u"OK", u"LEFT", u"RIGHT", u"~" ]] self.lang = 'en_US' self.nextLang = 'de_DE' self["country"].setText(self.lang) self.max_key = 47 + len(self.keys_list[4]) def virtualKeyBoardEntryComponent(self, keys): screenwidth = getDesktop(0).size().width() key_bg_width = self.key_bg and self.key_bg.size().width() or 45 key_images = self.shiftMode and self.keyImagesShift or self.keyImages res = [keys] text = [] x = 0 for key in keys: png = key_images.get(key, None) if png: width = png.size().width() if screenwidth and screenwidth == 1920: res.append( MultiContentEntryPixmapAlphaBlend(pos=(x, 0), size=(width, 68), png=png)) else: res.append( MultiContentEntryPixmapAlphaBlend(pos=(x, 0), size=(width, 45), png=png)) else: width = key_bg_width if screenwidth and screenwidth == 1920: res.append( MultiContentEntryPixmapAlphaBlend(pos=(x, 0), size=(width, 68), png=self.key_bg)) text.append( MultiContentEntryText(pos=(x, 0), size=(width, 68), font=1, text=key.encode("utf-8"), flags=RT_HALIGN_CENTER | RT_VALIGN_CENTER)) else: res.append( MultiContentEntryPixmapAlphaBlend(pos=(x, 0), size=(width, 45), png=self.key_bg)) text.append( MultiContentEntryText(pos=(x, 0), size=(width, 45), font=0, text=key.encode("utf-8"), flags=RT_HALIGN_CENTER | RT_VALIGN_CENTER)) x += width return res + text def buildVirtualKeyBoard(self): self.previousSelectedKey = None self.list = [] for keys in self.shiftMode and self.shiftkeys_list or self.keys_list: self.list.append(self.virtualKeyBoardEntryComponent(keys)) self.markSelectedKey() def markSelectedKey(self): screenwidth = getDesktop(0).size().width() if self.previousSelectedKey is not None: self.list[self.previousSelectedKey / 12] = self.list[self.previousSelectedKey / 12][:-1] width = self.key_sel.size().width() x = self.list[self.selectedKey / 12][self.selectedKey % 12 + 1][1] if screenwidth and screenwidth == 1920: self.list[self.selectedKey / 12].append( MultiContentEntryPixmapAlphaBlend(pos=(x, 0), size=(width, 68), png=self.key_sel)) else: self.list[self.selectedKey / 12].append( MultiContentEntryPixmapAlphaBlend(pos=(x, 0), size=(width, 45), png=self.key_sel)) self.previousSelectedKey = self.selectedKey self["list"].setList(self.list) def backClicked(self): self["text"].deleteBackward() def forwardClicked(self): self["text"].deleteForward() def shiftClicked(self): self.smsChar = None self.shiftMode = not self.shiftMode self.buildVirtualKeyBoard() def okClicked(self): self.smsChar = None text = (self.shiftMode and self.shiftkeys_list or self.keys_list)[self.selectedKey / 12][self.selectedKey % 12].encode("UTF-8") if text == "EXIT": self.close(None) elif text == "BACKSPACE": self["text"].deleteBackward() elif text == "ALL": self["text"].markAll() elif text == "CLEAR": self["text"].deleteAllChars() self["text"].update() elif text == "SHIFT": self.shiftClicked() elif text == "SPACE": self["text"].char(" ".encode("UTF-8")) elif text == "OK": self.close(self["text"].getText().encode("UTF-8")) elif text == "LEFT": self["text"].left() elif text == "RIGHT": self["text"].right() else: self["text"].char(text) def okLongClicked(self): self.smsChar = None text = (self.shiftMode and self.shiftkeys_list or self.keys_list)[self.selectedKey / 12][self.selectedKey % 12].encode("UTF-8") if text == "BACKSPACE": self["text"].deleteAllChars() self["text"].update() def ok(self): self.close(self["text"].getText().encode("UTF-8")) def exit(self): self.close(None) def cursorRight(self): self["text"].right() def cursorLeft(self): self["text"].left() def left(self): self.smsChar = None self.selectedKey = self.selectedKey / 12 * 12 + (self.selectedKey + 11) % 12 if self.selectedKey > self.max_key: self.selectedKey = self.max_key self.markSelectedKey() def right(self): self.smsChar = None self.selectedKey = self.selectedKey / 12 * 12 + (self.selectedKey + 1) % 12 if self.selectedKey > self.max_key: self.selectedKey = self.selectedKey / 12 * 12 self.markSelectedKey() def up(self): self.smsChar = None self.selectedKey -= 12 if self.selectedKey < 0: self.selectedKey = self.max_key / 12 * 12 + self.selectedKey % 12 if self.selectedKey > self.max_key: self.selectedKey -= 12 self.markSelectedKey() def down(self): self.smsChar = None self.selectedKey += 12 if self.selectedKey > self.max_key: self.selectedKey %= 12 self.markSelectedKey() def keyNumberGlobal(self, number): self.smsChar = self.sms.getKey(number) self.selectAsciiKey(self.smsChar) def smsOK(self): if self.smsChar and self.selectAsciiKey(self.smsChar): print "pressing ok now" self.okClicked() def keyGotAscii(self): self.smsChar = None if self.selectAsciiKey(str(unichr( getPrevAsciiCode()).encode('utf-8'))): self.okClicked() def selectAsciiKey(self, char): if char == " ": char = "SPACE" for keyslist in (self.shiftkeys_list, self.keys_list): selkey = 0 for keys in keyslist: for key in keys: if key == char: self.selectedKey = selkey if self.shiftMode != (keyslist is self.shiftkeys_list): self.shiftMode = not self.shiftMode self.buildVirtualKeyBoard() else: self.markSelectedKey() return True selkey += 1 return False
class EpgCenterList(GUIComponent): # some static stuff used by ["list"] and ["upcoming"] widgets infoBarInstance = None eServiceCenterInstance = None bouquetList = [] bouquetServices = [] currentBouquetIndex = 0 bouquetIndexRanges = [] allServicesNameDict = {} recordTimer = None lenChannelDigits = 0 def __init__(self, blinkTimer, listType, videoMode, piconLoader, bouquetList, currentIndex, piconSize, listStyle, epgList): self.blinkTimer = blinkTimer self.listType = listType self.videoMode = videoMode self.piconLoader = piconLoader self.piconSize = piconSize self.baseHeight = self.piconSize.height() self.listStyle = listStyle self.epgList = epgList GUIComponent.__init__(self) from Screens.InfoBar import InfoBar EpgCenterList.infoBarInstance = InfoBar.instance EpgCenterList.eServiceCenterInstance = eServiceCenter.getInstance() self.l = eListboxPythonMultiContent() self.l.setBuildFunc(self.buildEpgEntry) self.onSelectionChanged = [ ] if self.videoMode == MODE_SD or self.videoMode == MODE_XD: self.overallFontHeight = 36 elif self.videoMode == MODE_HD: self.overallFontHeight = 44 #initialize self.list = [] self.mode = None self.similarShown = False config.plugins.merlinEpgCenter.listItemHeight.addNotifier(self.changeHeight, initial_call = True) config.plugins.merlinEpgCenter.adjustFontSize.addNotifier(self.setFontSizes, initial_call = True) if listType == LIST_TYPE_EPG: EpgCenterList.bouquetList = bouquetList EpgCenterList.currentBouquetIndex = currentIndex EpgCenterList.updateBouquetServices() EpgCenterList.recordTimer = NavigationInstance.instance.RecordTimer # zap timer pixmaps self.zap_pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/zap.png")) self.zap_pre_pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/zap_pre.png")) self.zap_post_pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/zap_post.png")) self.zap_event_pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/zap_event.png")) self.zap_repeated_pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/zap_repeated.png")) self.zap_add_pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/zap_add.png")) # record timer pixmaps self.timer_pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/timer.png")) self.timer_pre_pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/timer_pre.png")) self.timer_post_pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/timer_post.png")) self.timer_event_pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/timer_event.png")) self.timer_repeated_pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/timer_repeated.png")) self.timer_add_pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/timer_add.png")) # progress pixmaps self.progressPixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/Progress.png")) self.progressPixmap_0 = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/Progress_0.png")) self.progressPixmap_1 = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/Progress_1.png")) self.progressPixmap_2 = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/Progress_2.png")) self.progressPixmap_3 = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/Progress_3.png")) self.progressPixmap_4 = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/Progress_4.png")) self.progressPixmapWidth = self.progressPixmap.size().width() self.epgcache = eEPGCache.getInstance() self.blinkTimer.callbacks.append(self.invalidateList) def onShow(self): self.maxWidth = self.l.getItemSize().width() def setFontSizes(self, configElement = None): diff = configElement.getValue() if self.videoMode == MODE_SD: self.l.setFont(0, gFont("Regular", 18 + diff)) self.l.setFont(1, gFont("Regular", 16 + diff)) self.l.setFont(2, gFont("Regular", 14 + diff)) self.l.setFont(3, gFont("Regular", 12 + diff)) elif self.videoMode == MODE_XD: self.l.setFont(0, gFont("Regular", 18 + diff)) self.l.setFont(1, gFont("Regular", 16 + diff)) self.l.setFont(2, gFont("Regular", 14 + diff)) self.l.setFont(3, gFont("Regular", 12 + diff)) elif self.videoMode == MODE_HD: self.l.setFont(0, gFont("Regular", 22 + diff)) self.l.setFont(1, gFont("Regular", 20 + diff)) self.l.setFont(2, gFont("Regular", 18 + diff)) self.l.setFont(3, gFont("Regular", 16 + diff)) def setMaxWidth(self, newSize): self.maxWidth = newSize.width() def changeHeight(self, configElement = None): self.listStyle = config.plugins.merlinEpgCenter.listStyle.value if self.listStyle == STYLE_SINGLE_LINE: self.singleLineBorder = 2 else: self.singleLineBorder = 0 if self.listStyle == STYLE_SHORT_DESCRIPTION or (self.listStyle == STYLE_SINGLE_LINE and (self.mode == SINGLE_EPG or self.mode == EPGSEARCH_RESULT or self.similarShown)): if self.overallFontHeight > self.baseHeight: self.itemHeight = self.overallFontHeight + int(config.plugins.merlinEpgCenter.listItemHeight.value) else: self.itemHeight = self.baseHeight + int(config.plugins.merlinEpgCenter.listItemHeight.value) elif self.videoMode == MODE_HD and config.plugins.merlinEpgCenter.listProgressStyle.value == STYLE_PERCENT_TEXT: # HD skin adjustment for text size self.itemHeight = self.baseHeight + int(config.plugins.merlinEpgCenter.listItemHeight.value) + 4 else: self.itemHeight = self.baseHeight + int(config.plugins.merlinEpgCenter.listItemHeight.value) self.halfItemHeight = self.itemHeight / 2 self.l.setItemHeight(self.itemHeight) def buildEpgEntry(self, ignoreMe, eventid, sRef, begin, duration, title, short, desc): columnSpace = config.plugins.merlinEpgCenter.columnSpace.getValue() progressPixmap = None offsetLeft = 5 offsetRight = self.maxWidth - 5 - 8 # 8 = timer pixmap width, 5 = border secondLineColor = 0x00909090 # grey border = int(config.plugins.merlinEpgCenter.listItemHeight.value) / 2 percent = 0 if begin != None and duration != None: timeString = strftime("%H:%M", localtime(begin)) + "-" + strftime("%H:%M", localtime(begin + duration)) now = int(time()) if now > begin: percent = (now - begin) * 100 / duration if self.mode == MULTI_EPG_NOW: timeValue = (begin + duration - now) / 60 +1 elif self.mode == MULTI_EPG_NEXT or self.mode == UPCOMING: timeValue = (now - begin) / 60 elif self.mode == MULTI_EPG_PRIMETIME or self.mode == EPGSEARCH_RESULT: if now >= begin: timeValue = (begin + duration - now) / 60 + 1 else: timeValue = (now - begin) / 60 elif self.mode == SINGLE_EPG: if self.instance.getCurrentIndex() == 0: timeValue = (begin + duration - now) / 60 + 1 else: timeValue = (now - begin) / 60 if config.plugins.merlinEpgCenter.showBeginRemainTime.value: if (KEEP_OUTDATED_TIME == 0 and (begin + duration) > now) or (KEEP_OUTDATED_TIME != 0 and (begin + duration) > now): if config.plugins.merlinEpgCenter.showDuration.value: remainBeginString = " I " else: remainBeginString = "" if timeValue >= 0: remainBeginString += "+" if fabs(timeValue) >= 120 and fabs(timeValue) < 1440: timeValue /= 60 remainBeginString += "%0dh" % timeValue elif fabs(timeValue) >= 1440: timeValue = (timeValue / 1440) +1 remainBeginString += "%02dd" % timeValue else: if timeValue < 0: remainBeginString += "%03d" % timeValue else: remainBeginString += "%02d" % timeValue else: if config.plugins.merlinEpgCenter.showDuration.value: remainBeginString = " I <->" else: remainBeginString = "<->" else: remainBeginString = "" if config.plugins.merlinEpgCenter.showDuration.value: duraString = "%d" % (duration / 60) if self.mode == MULTI_EPG_NOW: if config.plugins.merlinEpgCenter.listProgressStyle.value == STYLE_MULTI_PIXMAP: part = int(round(percent / 25)) + 1 progressPixmap = eval('self.progressPixmap_' + str(part)) elif config.plugins.merlinEpgCenter.listProgressStyle.value == STYLE_PIXMAP_BAR: progressPixmap = self.progressPixmap else: timeString = "" duraString = "" remainBeginString = "" if remainBeginString.endswith('>'): # KEEP_OUTDATED_TIME outdated = True try: progColor = parseColor("eventNotAvailable").argb() except: progColor = 0x777777 elif config.plugins.merlinEpgCenter.showBeginRemainTime.value and config.plugins.merlinEpgCenter.showColoredEpgTimes.value: outdated = False if remainBeginString.endswith('h'): # begins in... hours progColor = 0x00ef7f1a # brown elif remainBeginString.endswith('d'): # begins in... days progColor = 0x00e31e24 # red elif remainBeginString.startswith(' I +') or remainBeginString.startswith('+'): # already running progColor = 0x0074de0a # green elif remainBeginString.startswith(' I -') or remainBeginString.startswith('-'): # begins in... minutes progColor = 0x00ffed00 # yellow else: # undefined, shouldn't happen progColor = 0x00ffffff # white else: outdated = False progColor = 0x00ffed00 # yellow if outdated: textColor = progColor elif self.epgList != None: textColor = self.epgList.getColorEventAvailable(sRef, begin, duration) else: textColor = None res = [ None ] if config.plugins.merlinEpgCenter.showListNumbers.value: if ((self.mode == SINGLE_EPG and not self.similarShown) or self.mode == UPCOMING) and self.instance.getCurrentIndex() != 0: chNumber = "" else: # check if the service is found in our bouquets (or don't show the channel number if not found) if self.mode == EPGSEARCH_RESULT: if sRef in EpgCenterList.allServicesNameDict: i = 0 while i < len(EpgCenterList.bouquetServices): if sRef in EpgCenterList.bouquetServices[i]: chOffset = EpgCenterList.bouquetIndexRanges[i] chNumber = str(EpgCenterList.bouquetServices[i].index(sRef) + chOffset) break i += 1 else: chNumber = "" else: if sRef in EpgCenterList.bouquetServices[EpgCenterList.currentBouquetIndex]: chOffset = EpgCenterList.bouquetIndexRanges[EpgCenterList.currentBouquetIndex] chNumber = str(EpgCenterList.bouquetServices[EpgCenterList.currentBouquetIndex].index(sRef) + chOffset) else: chNumber = "" if EpgCenterList.lenChannelDigits < 3: width = self.maxWidth * 3 / 100 else: width = self.maxWidth * 4 / 100 res.append((eListboxPythonMultiContent.TYPE_TEXT, offsetLeft, 0, width, self.itemHeight, 1, RT_HALIGN_RIGHT|RT_VALIGN_CENTER, chNumber)) offsetLeft = offsetLeft + width + columnSpace if config.plugins.merlinEpgCenter.showPicons.value: if ((self.mode == SINGLE_EPG and not self.similarShown) or self.mode == UPCOMING) and self.instance.getCurrentIndex() != 0: picon = None else: picon = self.piconLoader.getPicon(sRef) width = self.piconSize.width() if picon: res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetLeft, (self.itemHeight - self.baseHeight) / 2, width, self.itemHeight, picon)) offsetLeft = offsetLeft + width + columnSpace if config.plugins.merlinEpgCenter.showServiceName.value: if self.videoMode == MODE_SD: width = self.maxWidth * 12 / 100 elif self.videoMode == MODE_XD: width = self.maxWidth * 14 / 100 elif self.videoMode == MODE_HD: width = self.maxWidth * 16 / 100 if not (((self.mode == SINGLE_EPG and not self.similarShown) or self.mode == UPCOMING) and self.instance.getCurrentIndex() != 0): if sRef in EpgCenterList.allServicesNameDict: serviceName = EpgCenterList.allServicesNameDict[sRef] else: serviceName = ServiceReference(sRef).getServiceName() res.append((eListboxPythonMultiContent.TYPE_TEXT, offsetLeft, 0, width, self.itemHeight, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, serviceName)) offsetLeft = offsetLeft + width + columnSpace if self.mode == MULTI_EPG_NOW and not self.similarShown: if self.videoMode == MODE_SD: width = self.maxWidth * 18 / 100 else: width = self.maxWidth * 14 / 100 progressHeight = 6 res.append((eListboxPythonMultiContent.TYPE_TEXT, offsetLeft, border, width, self.halfItemHeight - border + (self.singleLineBorder * 2), 1, RT_HALIGN_CENTER|RT_VALIGN_TOP, timeString)) if config.plugins.merlinEpgCenter.listProgressStyle.value == STYLE_MULTI_PIXMAP and progressPixmap is not None: if width > self.progressPixmapWidth: progressOffset = int((width - self.progressPixmapWidth) / 2) else: progressOffset = 0 res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetLeft + progressOffset, self.halfItemHeight + (self.halfItemHeight - progressHeight) / 2 + self.singleLineBorder, width, progressHeight, progressPixmap)) elif config.plugins.merlinEpgCenter.listProgressStyle.value == STYLE_SIMPLE_BAR: res.append((eListboxPythonMultiContent.TYPE_PROGRESS, offsetLeft, self.halfItemHeight + (self.halfItemHeight - progressHeight) / 2 + self.singleLineBorder, width, progressHeight, percent, 1, secondLineColor)) elif config.plugins.merlinEpgCenter.listProgressStyle.value == STYLE_PIXMAP_BAR and progressPixmap is not None: if width > self.progressPixmapWidth: progressOffset = int((width - self.progressPixmapWidth) / 2) else: progressOffset = 0 res.append((eListboxPythonMultiContent.TYPE_PROGRESS_PIXMAP, offsetLeft + progressOffset, self.halfItemHeight + (self.halfItemHeight - progressHeight) / 2 + self.singleLineBorder, width, progressHeight, percent, progressPixmap, 0)) elif config.plugins.merlinEpgCenter.listProgressStyle.value == STYLE_PERCENT_TEXT: if self.videoMode == MODE_SD: # we need a bigger font for SD skins font = 2 else: font = 3 res.append((eListboxPythonMultiContent.TYPE_TEXT, offsetLeft, self.halfItemHeight, width, self.halfItemHeight - border, font, RT_HALIGN_CENTER|RT_VALIGN_TOP, str(percent) + "%", secondLineColor)) offsetLeft = offsetLeft + width + columnSpace else: if self.videoMode == MODE_SD: width = self.maxWidth * 18 / 100 else: width = self.maxWidth * 14 / 100 if self.mode == SINGLE_EPG or self.mode == EPGSEARCH_RESULT or self.similarShown: fd = getFuzzyDay(begin) res.append((eListboxPythonMultiContent.TYPE_TEXT, offsetLeft, border, width, self.halfItemHeight - border, 1, RT_HALIGN_CENTER|RT_VALIGN_TOP, timeString, textColor)) res.append((eListboxPythonMultiContent.TYPE_TEXT, offsetLeft, self.halfItemHeight, width, self.halfItemHeight - border, 2, RT_HALIGN_CENTER|RT_VALIGN_TOP, fd, secondLineColor)) else: res.append((eListboxPythonMultiContent.TYPE_TEXT, offsetLeft, 0, width, self.itemHeight, 1, RT_HALIGN_CENTER|RT_VALIGN_CENTER, timeString, textColor)) offsetLeft = offsetLeft + width + columnSpace if begin != None and duration != None: (timerPixmaps, zapPixmaps, isRunning) = self.getTimerPixmapsForEntry(sRef, eventid, begin, duration) else: timerPixmaps = 0 zapPixmaps = 0 isRunning = 0 idx = self.instance.getCurrentIndex() self.blinkTimer.updateEntry(self.listType, idx, isRunning) if zapPixmaps: if (zapPixmaps & TIMER_TYPE_EID_MATCH) or (zapPixmaps & TIMER_TYPE_COVERS_FULL) or (zapPixmaps & TIMER_TYPE_EID_REPEATED) or (zapPixmaps & TIMER_TYPE_ADD_COVERS_FULL): posY = 2 height = self.itemHeight - 4 if (zapPixmaps & TIMER_TYPE_EID_MATCH): res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.zap_event_pixmap)) elif (zapPixmaps & TIMER_TYPE_COVERS_FULL): res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.zap_pixmap)) elif (zapPixmaps & TIMER_TYPE_EID_REPEATED): res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.zap_repeated_pixmap)) elif (zapPixmaps & TIMER_TYPE_ADD_COVERS_FULL): res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.zap_add_pixmap)) elif (zapPixmaps & TIMER_TYPE_INSIDE_EVENT) or (zapPixmaps & TIMER_TYPE_ADD_INSIDE_EVENT): posY = self.itemHeight / 2 - 6 height = 12 if (zapPixmaps & TIMER_TYPE_INSIDE_EVENT): res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.zap_pixmap)) elif (zapPixmaps & TIMER_TYPE_ADD_INSIDE_EVENT): res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.zap_add_pixmap)) else: if zapPixmaps & TIMER_TYPE_COVERS_END: posY = self.itemHeight / 2 + 2 height = self.itemHeight - posY - 2 res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.zap_pre_pixmap)) elif zapPixmaps & TIMER_TYPE_ADD_COVERS_END: posY = self.itemHeight / 2 + 2 height = self.itemHeight - posY - 2 res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.zap_add_pixmap)) if zapPixmaps & TIMER_TYPE_COVERS_BEGIN: posY = 2 height = self.itemHeight / 2 - 2 res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.zap_post_pixmap)) elif zapPixmaps & TIMER_TYPE_ADD_COVERS_BEGIN: posY = 2 height = self.itemHeight / 2 - 2 res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.zap_add_pixmap)) if zapPixmaps & TIMER_TYPE_ADD: posY = 2 height = self.itemHeight - 4 res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.zap_add_pixmap)) offsetRight -= 10 if timerPixmaps: if (timerPixmaps & TIMER_TYPE_EID_MATCH) or (timerPixmaps & TIMER_TYPE_COVERS_FULL) or (timerPixmaps & TIMER_TYPE_EID_REPEATED) or (timerPixmaps & TIMER_TYPE_ADD_COVERS_FULL): posY = 2 height = self.itemHeight - 4 if (timerPixmaps & TIMER_TYPE_EID_MATCH): if (isRunning & TIMER_TYPE_EID_MATCH) and not self.blinkTimer.getBlinkState(): res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, None)) else: res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.timer_event_pixmap)) elif (timerPixmaps & TIMER_TYPE_COVERS_FULL): if (isRunning & TIMER_TYPE_COVERS_FULL) and not self.blinkTimer.getBlinkState(): res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, None)) else: res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.timer_pixmap)) elif (timerPixmaps & TIMER_TYPE_EID_REPEATED): if (isRunning & TIMER_TYPE_EID_REPEATED) and not self.blinkTimer.getBlinkState(): res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, None)) else: res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.timer_repeated_pixmap)) elif (timerPixmaps & TIMER_TYPE_ADD_COVERS_FULL): res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.timer_add_pixmap)) elif (timerPixmaps & TIMER_TYPE_INSIDE_EVENT) or (timerPixmaps & TIMER_TYPE_ADD_INSIDE_EVENT): posY = self.itemHeight / 2 - 6 height = 12 if (timerPixmaps & TIMER_TYPE_INSIDE_EVENT): if (isRunning & TIMER_TYPE_INSIDE_EVENT) and not self.blinkTimer.getBlinkState(): res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, None)) else: res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.timer_pixmap)) elif (timerPixmaps & TIMER_TYPE_ADD_INSIDE_EVENT): res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.timer_add_pixmap)) else: if timerPixmaps & TIMER_TYPE_COVERS_END: posY = self.itemHeight / 2 + 2 height = self.itemHeight - posY - 2 if (isRunning & TIMER_TYPE_COVERS_END) and not self.blinkTimer.getBlinkState(): res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, None)) else: res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.timer_pre_pixmap)) elif timerPixmaps & TIMER_TYPE_ADD_COVERS_END: posY = self.itemHeight / 2 + 2 height = self.itemHeight - posY - 2 res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.timer_add_pixmap)) if timerPixmaps & TIMER_TYPE_COVERS_BEGIN: posY = 2 height = self.itemHeight / 2 - 2 if (isRunning & TIMER_TYPE_COVERS_BEGIN) and not self.blinkTimer.getBlinkState(): res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, None)) else: res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.timer_post_pixmap)) elif timerPixmaps & TIMER_TYPE_ADD_COVERS_BEGIN: posY = 2 height = self.itemHeight / 2 - 2 res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.timer_add_pixmap)) if timerPixmaps & TIMER_TYPE_ADD: posY = 2 height = self.itemHeight - 4 res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.timer_add_pixmap)) if config.plugins.merlinEpgCenter.showBeginRemainTime.value and config.plugins.merlinEpgCenter.showDuration.value: width = self.maxWidth * 8 / 100 offsetRight = offsetRight - width res.append((eListboxPythonMultiContent.TYPE_TEXT, offsetRight, 0, width, self.itemHeight, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, remainBeginString, progColor)) elif config.plugins.merlinEpgCenter.showBeginRemainTime.value: width = self.maxWidth * 6 / 100 offsetRight = offsetRight - width res.append((eListboxPythonMultiContent.TYPE_TEXT, offsetRight, 0, width, self.itemHeight, 1, RT_HALIGN_RIGHT|RT_VALIGN_CENTER, remainBeginString, progColor)) if config.plugins.merlinEpgCenter.showDuration.value: width = self.maxWidth * 6 / 100 offsetRight = offsetRight - width elif not config.plugins.merlinEpgCenter.showDuration.value and not config.plugins.merlinEpgCenter.showBeginRemainTime.value: width = self.maxWidth * 1 / 100 offsetRight = offsetRight - width titleWidth = offsetRight - offsetLeft - columnSpace if self.listStyle == STYLE_SINGLE_LINE: res.append((eListboxPythonMultiContent.TYPE_TEXT, offsetLeft, 0, titleWidth, self.itemHeight, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, title, config.plugins.merlinEpgCenter.titleColor.value, config.plugins.merlinEpgCenter.titleColorSelected.value)) elif self.listStyle == STYLE_SHORT_DESCRIPTION: if short and title != short: res.append((eListboxPythonMultiContent.TYPE_TEXT, offsetLeft, border, titleWidth, self.halfItemHeight - border, 1, RT_HALIGN_LEFT|RT_VALIGN_TOP, title, textColor)) res.append((eListboxPythonMultiContent.TYPE_TEXT, offsetLeft, self.halfItemHeight, titleWidth, self.halfItemHeight - border, 2, RT_HALIGN_LEFT|RT_VALIGN_TOP, short, secondLineColor)) else: res.append((eListboxPythonMultiContent.TYPE_TEXT, offsetLeft, 0, titleWidth, self.itemHeight, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, title, textColor)) if config.plugins.merlinEpgCenter.showDuration.value: res.append((eListboxPythonMultiContent.TYPE_TEXT, offsetRight, 0, width, self.itemHeight, 1, RT_HALIGN_RIGHT|RT_VALIGN_CENTER, duraString, textColor)) return res GUI_WIDGET = eListbox def selectionChanged(self): for x in self.onSelectionChanged: x() def postWidgetCreate(self, instance): instance.setWrapAround(True) instance.setContent(self.l) instance.selectionChanged.get().append(self.selectionChanged) def preWidgetRemove(self, instance): instance.setContent(None) instance.selectionChanged.get().remove(self.selectionChanged) config.plugins.merlinEpgCenter.listItemHeight.removeNotifier(self.changeHeight) config.plugins.merlinEpgCenter.adjustFontSize.removeNotifier(self.setFontSizes) self.blinkTimer.callbacks.remove(self.invalidateList) def moveToIndex(self, index): self.instance.moveSelectionTo(index) def moveUp(self): self.instance.moveSelection(self.instance.moveUp) def moveDown(self): self.instance.moveSelection(self.instance.moveDown) def pageUp(self): if self.instance is not None: self.instance.moveSelection(self.instance.pageUp) def pageDown(self): if self.instance is not None: self.instance.moveSelection(self.instance.pageDown) def getCurrent(self): return self.l.getCurrentSelection() def invalidate(self, entry): # when the entry to invalidate does not exist, just ignore the request. # this eases up conditional setup screens a lot. if entry in self.list: self.l.invalidateEntry(self.list.index(entry)) def invalidateList(self): self.l.invalidate() def setList(self, l): self.list = l self.l.setList(self.list) def queryEPG(self, servicelist): if self.epgcache is not None: return self.epgcache.lookupEvent(servicelist) return [ ] def fillMultiEPG(self, bouquet, bouquetIndex, mode, stime=-1): EpgCenterList.currentBouquetIndex = bouquetIndex # 1. if oldmode is MULTI_EPG_NOW and new mode is MULTI_EPG_NEXT --> use old list for querying EPG (speed up! :-) ) # 2. otherwise build servicelist from bouquet, and # a) if MULTI_EPG_NOW/MULTI_EPG_PRIMETIME --> query epg # b) if MULTI_EPG_NEXT --> build query-list with servicelist for epg oldmode = self.mode self.mode = mode self.similarShown = False if ((mode == MULTI_EPG_NOW or mode == MULTI_EPG_PRIMETIME) or (oldmode != MULTI_EPG_NOW and mode == MULTI_EPG_NEXT)): servicelist = EpgCenterList.getServiceList(bouquet, stime) returnTuples = '0IRBDTSEX' if mode == MULTI_EPG_NOW or mode == MULTI_EPG_PRIMETIME: servicelist.insert(0, returnTuples) else: if oldmode != MULTI_EPG_NOW: servicelist.insert(0, returnTuples) tmpList = self.queryEPG(servicelist) else: tmpList = self.list servicelist = [ x[3] and (x[2], 1, x[3]) or (x[2], 1, 0) for x in tmpList ] # build servicelist with "event after given start_time" and set the start time servicelist.insert(0, returnTuples) if self.listStyle == STYLE_SINGLE_LINE: self.changeHeight() self.list = self.queryEPG(servicelist) self.l.setList(self.list) def fillSingleEPG(self, bouquet, bouquetIndex, mode, sRef, showOutdated): self.mode = mode EpgCenterList.currentBouquetIndex = bouquetIndex EpgCenterList.getServiceList(bouquet) self.similarShown = False if sRef: if showOutdated: now = time() queryString = [ '0IRBDTSE', (sRef, 0, now - KEEP_OUTDATED_TIME * 60, KEEP_OUTDATED_TIME) ] else: queryString = [ '0IRBDTSE', (sRef, 0, -1, -1) ] self.list = self.queryEPG(queryString) if self.listStyle == STYLE_SINGLE_LINE: self.changeHeight() if showOutdated: self.list.sort(key = lambda x: x[3], reverse = True) # sort by time self.l.setList(self.list) def fillSimilar(self, sRef, eventId): if eventId is None: return self.similarShown = True self.list = self.epgcache.search(('0IRBDTSE', 1024, eEPGCache.SIMILAR_BROADCASTINGS_SEARCH, sRef, eventId)) if self.list is not None: if config.plugins.merlinEpgCenter.limitSearchToBouquetServices.value: for item in self.list[:]: if not item[2] in EpgCenterList.allServicesNameDict: self.list.remove(item) if self.listStyle == STYLE_SINGLE_LINE: self.changeHeight() self.list.sort(key = lambda x: x[3]) # sort by time self.l.setList(self.list) def fillEpgSearch(self, searchString, mode): self.mode = mode self.similarShown = False if searchString == None: self.list = [] else: searchString = searchString.decode('utf-8').encode("iso-8859-1","replace") self.list = self.epgcache.search(('0IRBDTSE', 1024, eEPGCache.PARTIAL_TITLE_SEARCH, searchString, eEPGCache.NO_CASE_CHECK)) or [] if config.plugins.merlinEpgCenter.limitSearchToBouquetServices.value: for item in self.list[:]: if not item[2] in EpgCenterList.allServicesNameDict: self.list.remove(item) self.list.sort(key = lambda x: x[3]) # sort by time if self.listStyle == STYLE_SINGLE_LINE: self.changeHeight() self.l.setList(self.list) @staticmethod def getServiceList(bouquet, stime=-1, sRefOnly = False): services = [ ] servicelist = eServiceCenter.getInstance().list(bouquet) if not servicelist is None: while True: service = servicelist.getNext() if not service.valid(): # check if end of list break if service.flags & (eServiceReference.isDirectory | eServiceReference.isMarker): # ignore non playable services continue # alternative service? if service.flags & (eServiceReference.isGroup): altRoot = eServiceReference(service.toCompareString()) altList = EpgCenterList.eServiceCenterInstance.list(altRoot) if altList: while True: nextService = altList.getNext() if not nextService.valid(): break service = nextService break if sRefOnly: services.append(service.toCompareString()) else: services.append((service.toCompareString(), 0, stime)) return services # get a list of all services in all bouquets @staticmethod def getAllServices(): allServices = {} index = 1 EpgCenterList.lenChannelDigits = 0 totalServices = 0 # the number of services in all bouquets for bouquetEntry in EpgCenterList.bouquetList: servicelist = eServiceCenter.getInstance().list(bouquetEntry[1]) if not servicelist is None: numServices = 0 while True: service = servicelist.getNext() if not service.valid(): # check if end of list break if service.flags & (eServiceReference.isDirectory | eServiceReference.isMarker): # ignore non playable services continue info = EpgCenterList.eServiceCenterInstance.info(service) serviceName = info.getName(service) or ServiceReference(service).getServiceName() or "" allServices[service.toCompareString()] = serviceName numServices += 1 indexEntry = index index += numServices totalServices += numServices EpgCenterList.bouquetIndexRanges.append(indexEntry) EpgCenterList.lenChannelDigits = len(str(totalServices)) return allServices @staticmethod def updateBouquetServices(): EpgCenterList.bouquetIndexRanges = [] EpgCenterList.allServicesNameDict = EpgCenterList.getAllServices() EpgCenterList.bouquetServices = [] for bouquet in EpgCenterList.bouquetList: EpgCenterList.bouquetServices.append(EpgCenterList.getServiceList(bouquet[1], sRefOnly = True)) def selectionEnabled(self, enabled): if self.instance is not None: self.instance.setSelectionEnable(enabled) def getTimerPixmapsForEntry(self, sRef, eventId, begin, duration): timerPixmaps = 0 zapPixmaps = 0 isRunning = 0 for timer in self.recordTimer.timer_list: if timer.service_ref.ref.toString() == sRef: end = begin + duration if timer.begin > begin and timer.end < end: # the timer is inside the events bounds if timer.justplay: zapPixmaps |= TIMER_TYPE_INSIDE_EVENT else: timerPixmaps |= TIMER_TYPE_INSIDE_EVENT if timer.isRunning(): isRunning |= TIMER_TYPE_INSIDE_EVENT elif end >= timer.begin and begin <= timer.end: # this event touches the timer if eventId == timer.eit: # exact event match if timer.repeated: if timer.justplay: zapPixmaps |= TIMER_TYPE_EID_REPEATED else: timerPixmaps |= TIMER_TYPE_EID_REPEATED if timer.isRunning(): isRunning |= TIMER_TYPE_EID_REPEATED else: if timer.justplay: zapPixmaps |= TIMER_TYPE_EID_MATCH else: timerPixmaps |= TIMER_TYPE_EID_MATCH if timer.isRunning(): isRunning |= TIMER_TYPE_EID_MATCH elif begin < timer.begin and end > timer.begin: # this event overlaps the end of the timer if timer.justplay: zapPixmaps |= TIMER_TYPE_COVERS_END else: timerPixmaps |= TIMER_TYPE_COVERS_END if timer.isRunning(): isRunning |= TIMER_TYPE_COVERS_END elif end > timer.end and begin < timer.end: # this event overlaps the begin of the timer if timer.justplay: zapPixmaps |= TIMER_TYPE_COVERS_BEGIN else: timerPixmaps |= TIMER_TYPE_COVERS_BEGIN if timer.isRunning(): isRunning |= TIMER_TYPE_COVERS_BEGIN elif end > timer.begin and begin < timer.end: # this event fully overlaps the timer but itsn't nor the timer event if timer.justplay: zapPixmaps |= TIMER_TYPE_COVERS_FULL else: timerPixmaps |= TIMER_TYPE_COVERS_FULL if timer.isRunning(): isRunning |= TIMER_TYPE_COVERS_FULL elif timerPixmaps == 0 and zapPixmaps == 0 and self.recordTimer.isInTimer(eventId, begin, duration, sRef): # timer repetition # TODO do we need to care about local times? timerBegin = datetime.fromtimestamp(timer.begin).time() timerEnd = datetime.fromtimestamp(timer.end).time() netTimerBegin = datetime.fromtimestamp(int(timer.begin) + 60 * config.recording.margin_before.value).time() netTimerEnd = datetime.fromtimestamp(int(timer.end) - 60 * config.recording.margin_after.value).time() eventBegin = datetime.fromtimestamp(begin).time() eventEnd = datetime.fromtimestamp(end).time() if netTimerBegin == eventBegin and netTimerEnd == eventEnd: # the main timer entry if timer.justplay: zapPixmaps |= TIMER_TYPE_ADD else: timerPixmaps |= TIMER_TYPE_ADD elif netTimerBegin >= eventBegin and netTimerEnd <= eventEnd: # the timer is inside the events bounds if timer.justplay: zapPixmaps |= TIMER_TYPE_ADD_INSIDE_EVENT else: timerPixmaps |= TIMER_TYPE_ADD_INSIDE_EVENT elif eventBegin < timerBegin and eventEnd > timerBegin: # this event overlaps the end of the timer if timer.justplay: zapPixmaps |= TIMER_TYPE_ADD_COVERS_END else: timerPixmaps |= TIMER_TYPE_ADD_COVERS_END elif eventEnd > timerEnd and eventBegin < timerEnd: # this event overlaps the begin of the timer if timer.justplay: zapPixmaps |= TIMER_TYPE_ADD_COVERS_BEGIN else: timerPixmaps |= TIMER_TYPE_ADD_COVERS_BEGIN elif eventEnd > timerBegin and eventBegin < timerEnd: # this event fully overlaps the timer but itsn't nor the timer event if timer.justplay: zapPixmaps |= TIMER_TYPE_ADD_COVERS_FULL else: timerPixmaps |= TIMER_TYPE_ADD_COVERS_FULL return timerPixmaps, zapPixmaps, isRunning
class VirtualKeyBoard(Screen): def __init__(self, session, title = '', **kwargs): Screen.__init__(self, session) self.setTitle(_('Virtual KeyBoard')) self.keys_list = [] self.shiftkeys_list = [] self.lang = language.getLanguage() self.nextLang = None self.shiftMode = False self.selectedKey = 0 self.smsChar = None self.sms = NumericalTextInput(self.smsOK) self.key_bg = LoadPixmap(path=resolveFilename(SCOPE_ACTIVE_SKIN, 'buttons/vkey_bg.png')) self.key_sel = LoadPixmap(path=resolveFilename(SCOPE_ACTIVE_SKIN, 'buttons/vkey_sel.png')) self.key_backspace = LoadPixmap(path=resolveFilename(SCOPE_ACTIVE_SKIN, 'buttons/vkey_backspace.png')) self.key_all = LoadPixmap(path=resolveFilename(SCOPE_ACTIVE_SKIN, 'buttons/vkey_all.png')) self.key_clr = LoadPixmap(path=resolveFilename(SCOPE_ACTIVE_SKIN, 'buttons/vkey_clr.png')) self.key_esc = LoadPixmap(path=resolveFilename(SCOPE_ACTIVE_SKIN, 'buttons/vkey_esc.png')) self.key_ok = LoadPixmap(path=resolveFilename(SCOPE_ACTIVE_SKIN, 'buttons/vkey_ok.png')) self.key_shift = LoadPixmap(path=resolveFilename(SCOPE_ACTIVE_SKIN, 'buttons/vkey_shift.png')) self.key_shift_sel = LoadPixmap(path=resolveFilename(SCOPE_ACTIVE_SKIN, 'buttons/vkey_shift_sel.png')) self.key_space = LoadPixmap(path=resolveFilename(SCOPE_ACTIVE_SKIN, 'buttons/vkey_space.png')) self.key_left = LoadPixmap(path=resolveFilename(SCOPE_ACTIVE_SKIN, 'buttons/vkey_left.png')) self.key_right = LoadPixmap(path=resolveFilename(SCOPE_ACTIVE_SKIN, 'buttons/vkey_right.png')) self.keyImages = {'BACKSPACE': self.key_backspace, 'ALL': self.key_all, 'EXIT': self.key_esc, 'OK': self.key_ok, 'SHIFT': self.key_shift, 'SPACE': self.key_space, 'LEFT': self.key_left, 'RIGHT': self.key_right} self.keyImagesShift = {'BACKSPACE': self.key_backspace, 'CLEAR': self.key_clr, 'EXIT': self.key_esc, 'OK': self.key_ok, 'SHIFT': self.key_shift_sel, 'SPACE': self.key_space, 'LEFT': self.key_left, 'RIGHT': self.key_right} self['country'] = StaticText('') self['header'] = Label() self['text'] = Input(currPos=len(kwargs.get('text', '').decode('utf-8', 'ignore')), allMarked=False, **kwargs) self['list'] = VirtualKeyBoardList([]) self['actions'] = NumberActionMap(['OkCancelActions', 'WizardActions', 'ColorActions', 'KeyboardInputActions', 'InputBoxActions', 'InputAsciiActions'], {'gotAsciiCode': self.keyGotAscii, 'ok': self.okClicked, 'OKLong': self.okLongClicked, 'cancel': self.exit, 'left': self.left, 'right': self.right, 'up': self.up, 'down': self.down, 'red': self.exit, 'green': self.ok, 'yellow': self.switchLang, 'blue': self.shiftClicked, 'deleteBackward': self.backClicked, 'deleteForward': self.forwardClicked, 'back': self.exit, 'pageUp': self.cursorRight, 'pageDown': self.cursorLeft, '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}, -2) self.setLang() self.onExecBegin.append(self.setKeyboardModeAscii) self.onLayoutFinish.append(self.buildVirtualKeyBoard) self.onClose.append(self.__onClose) return def __onClose(self): self.sms.timer.stop() def switchLang(self): self.lang = self.nextLang self.setLang() self.buildVirtualKeyBoard() def setLang(self): if self.lang == 'de_DE': self.keys_list = [[u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE'], [u'q', u'w', u'e', u'r', u't', u'z', u'u', u'i', u'o', u'p', u'\xfc', u'+'], [u'a', u's', u'd', u'f', u'g', u'h', u'j', u'k', u'l', u'\xf6', u'\xe4', u'#'], [u'<', u'y', u'x', u'c', u'v', u'b', u'n', u'm', u',', '.', u'-', u'ALL'], [u'SHIFT', u'SPACE', u'@', u'\xdf', u'OK', u'LEFT', u'RIGHT']] self.shiftkeys_list = [[u'EXIT', u'!', u'"', u'\xa7', u'$', u'%', u'&', u'/', u'(', u')', u'=', u'BACKSPACE'], [u'Q', u'W', u'E', u'R', u'T', u'Z', u'U', u'I', u'O', u'P', u'\xdc', u'*'], [u'A', u'S', u'D', u'F', u'G', u'H', u'J', u'K', u'L', u'\xd6', u'\xc4', u"'"], [u'>', u'Y', u'X', u'C', u'V', u'B', u'N', u'M', u';', u':', u'_', u'CLEAR'], [u'SHIFT', u'SPACE', u'?', u'\\', u'OK', u'LEFT', u'RIGHT']] self.nextLang = 'es_ES' elif self.lang == 'es_ES': self.keys_list = [[u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE'], [u'q', u'w', u'e', u'r', u't', u'z', u'u', u'i', u'o', u'p', u'\xfa', u'+'], [u'a', u's', u'd', u'f', u'g', u'h', u'j', u'k', u'l', u'\xf3', u'\xe1', u'#'], [u'<', u'y', u'x', u'c', u'v', u'b', u'n', u'm', u',', '.', u'-', u'ALL'], [u'SHIFT', u'SPACE', u'@', u'\u0141', u'\u0155', u'\xe9', u'\u010d', u'\xed', u'\u011b', u'\u0144', u'\u0148', u'OK']] self.shiftkeys_list = [[u'EXIT', u'!', u'"', u'\xa7', u'$', u'%', u'&', u'/', u'(', u')', u'=', u'BACKSPACE'], [u'Q', u'W', u'E', u'R', u'T', u'Z', u'U', u'I', u'O', u'P', u'\xda', u'*'], [u'A', u'S', u'D', u'F', u'G', u'H', u'J', u'K', u'L', u'\xd3', u'\xc1', u"'"], [u'>', u'Y', u'X', u'C', u'V', u'B', u'N', u'M', u';', u':', u'_', u'CLEAR'], [u'SHIFT', u'SPACE', u'?', u'\\', u'\u0154', u'\xc9', u'\u010c', u'\xcd', u'\u011a', u'\u0143', u'\u0147', u'OK']] self.nextLang = 'fi_FI' elif self.lang == 'fi_FI': self.keys_list = [[u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE'], [u'q', u'w', u'e', u'r', u't', u'z', u'u', u'i', u'o', u'p', u'\xe9', u'+'], [u'a', u's', u'd', u'f', u'g', u'h', u'j', u'k', u'l', u'\xf6', u'\xe4', u'#'], [u'<', u'y', u'x', u'c', u'v', u'b', u'n', u'm', u',', '.', u'-', u'ALL'], [u'SHIFT', u'SPACE', u'@', u'\xdf', u'\u013a', u'OK', u'LEFT', u'RIGHT']] self.shiftkeys_list = [[u'EXIT', u'!', u'"', u'\xa7', u'$', u'%', u'&', u'/', u'(', u')', u'=', u'BACKSPACE'], [u'Q', u'W', u'E', u'R', u'T', u'Z', u'U', u'I', u'O', u'P', u'\xc9', u'*'], [u'A', u'S', u'D', u'F', u'G', u'H', u'J', u'K', u'L', u'\xd6', u'\xc4', u"'"], [u'>', u'Y', u'X', u'C', u'V', u'B', u'N', u'M', u';', u':', u'_', u'CLEAR'], [u'SHIFT', u'SPACE', u'?', u'\\', u'\u0139', u'OK', u'LEFT', u'RIGHT']] self.nextLang = 'lv_LV' elif self.lang == 'lv_LV': self.keys_list = [[u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE'], [u'q', u'w', u'e', u'r', u't', u'y', u'u', u'i', u'o', u'p', u'-', u'\u0161'], [u'a', u's', u'd', u'f', u'g', u'h', u'j', u'k', u'l', u';', u"'", u'\u016b'], [u'<', u'z', u'x', u'c', u'v', u'b', u'n', u'm', u',', u'.', u'\u017e', u'ALL'], [u'SHIFT', u'SPACE', u'\u0101', u'\u010d', u'\u0113', u'\u0123', u'\u012b', u'\u0137', u'\u013c', u'\u0146', u'LEFT', u'RIGHT']] self.shiftkeys_list = [[u'EXIT', u'!', u'@', u'$', u'*', u'(', u')', u'_', u'=', u'/', u'\\', u'BACKSPACE'], [u'Q', u'W', u'E', u'R', u'T', u'Y', u'U', u'I', u'O', u'P', u'+', u'\u0160'], [u'A', u'S', u'D', u'F', u'G', u'H', u'J', u'K', u'L', u':', u'"', u'\u016a'], [u'>', u'Z', u'X', u'C', u'V', u'B', u'N', u'M', u'#', u'?', u'\u017d', u'CLEAR'], [u'SHIFT', u'SPACE', u'\u0100', u'\u010c', u'\u0112', u'\u0122', u'\u012a', u'\u0136', u'\u013b', u'\u0145', u'LEFT', u'RIGHT']] self.nextLang = 'ru_RU' elif self.lang == 'ru_RU': self.keys_list = [[u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE'], [u'\u0430', u'\u0431', u'\u0432', u'\u0433', u'\u0434', u'\u0435', u'\u0451', u'\u0436', u'\u0437', u'\u0438', u'\u0439', u'+'], [u'\u043a', u'\u043b', u'\u043c', u'\u043d', u'\u043e', u'\u043f', u'\u0440', u'\u0441', u'\u0442', u'\u0443', u'\u0444', u'#'], [u'<', u'\u0445', u'\u0446', u'\u0447', u'\u0448', u'\u0449', u'\u044a', u'\u044b', u',', u'.', u'-', u'ALL'], [u'SHIFT', u'SPACE', u'@', u'\u044c', u'\u044d', u'\u044e', u'\u044f', u'OK', u'LEFT', u'RIGHT']] self.shiftkeys_list = [[u'EXIT', u'!', u'"', u'\xa7', u'$', u'%', u'&', u'/', u'(', u')', u'=', u'BACKSPACE'], [u'\u0410', u'\u0411', u'\u0412', u'\u0413', u'\u0414', u'\u0415', u'\u0401', u'\u0416', u'\u0417', u'\u0418', u'\u0419', u'*'], [u'\u041a', u'\u041b', u'\u041c', u'\u041d', u'\u041e', u'\u041f', u'\u0420', u'\u0421', u'\u0422', u'\u0423', u'\u0424', u"'"], [u'>', u'\u0425', u'\u0426', u'\u0427', u'\u0428', u'\u0429', u'\u042a', u'\u042b', u';', u':', u'_', u'CLEAR'], [u'SHIFT', u'SPACE', u'?', u'\\', u'\u042c', u'\u042d', u'\u042e', u'\u042f', u'OK', u'LEFT', u'RIGHT']] self.nextLang = 'sv_SE' elif self.lang == 'sv_SE': self.keys_list = [[u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE'], [u'q', u'w', u'e', u'r', u't', u'z', u'u', u'i', u'o', u'p', u'\xe9', u'+'], [u'a', u's', u'd', u'f', u'g', u'h', u'j', u'k', u'l', u'\xf6', u'\xe4', u'#'], [u'<', u'y', u'x', u'c', u'v', u'b', u'n', u'm', u',', '.', u'-', u'ALL'], [u'SHIFT', u'SPACE', u'@', u'\xdf', u'\u013a', u'OK', u'LEFT', u'RIGHT']] self.shiftkeys_list = [[u'EXIT', u'!', u'"', u'\xa7', u'$', u'%', u'&', u'/', u'(', u')', u'=', u'BACKSPACE'], [u'Q', u'W', u'E', u'R', u'T', u'Z', u'U', u'I', u'O', u'P', u'\xc9', u'*'], [u'A', u'S', u'D', u'F', u'G', u'H', u'J', u'K', u'L', u'\xd6', u'\xc4', u"'"], [u'>', u'Y', u'X', u'C', u'V', u'B', u'N', u'M', u';', u':', u'_', u'CLEAR'], [u'SHIFT', u'SPACE', u'?', u'\\', u'\u0139', u'OK', u'LEFT', u'RIGHT']] self.nextLang = 'sk_SK' elif self.lang == 'sk_SK': self.keys_list = [[u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE'], [u'q', u'w', u'e', u'r', u't', u'z', u'u', u'i', u'o', u'p', u'\xfa', u'+'], [u'a', u's', u'd', u'f', u'g', u'h', u'j', u'k', u'l', u'\u013e', u'@', u'#'], [u'<', u'y', u'x', u'c', u'v', u'b', u'n', u'm', u',', '.', u'-', u'ALL'], [u'SHIFT', u'SPACE', u'\u0161', u'\u010d', u'\u017e', u'\xfd', u'\xe1', u'\xed', u'\xe9', u'OK', u'LEFT', u'RIGHT']] self.shiftkeys_list = [[u'EXIT', u'!', u'"', u'\xa7', u'$', u'%', u'&', u'/', u'(', u')', u'=', u'BACKSPACE'], [u'Q', u'W', u'E', u'R', u'T', u'Z', u'U', u'I', u'O', u'P', u'\u0165', u'*'], [u'A', u'S', u'D', u'F', u'G', u'H', u'J', u'K', u'L', u'\u0148', u'\u010f', u"'"], [u'\xc1', u'\xc9', u'\u010e', u'\xcd', u'\xdd', u'\xd3', u'\xda', u'\u017d', u'\u0160', u'\u010c', u'\u0164', u'\u0147'], [u'>', u'Y', u'X', u'C', u'V', u'B', u'N', u'M', u';', u':', u'_', u'CLEAR'], [u'SHIFT', u'SPACE', u'?', u'\\', u'\xe4', u'\xf6', u'\xfc', u'\xf4', u'\u0155', u'\u013a', u'OK']] self.nextLang = 'cs_CZ' elif self.lang == 'cs_CZ': self.keys_list = [[u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE'], [u'q', u'w', u'e', u'r', u't', u'z', u'u', u'i', u'o', u'p', u'\xfa', u'+'], [u'a', u's', u'd', u'f', u'g', u'h', u'j', u'k', u'l', u'\u016f', u'@', u'#'], [u'<', u'y', u'x', u'c', u'v', u'b', u'n', u'm', u',', '.', u'-', u'ALL'], [u'SHIFT', u'SPACE', u'\u011b', u'\u0161', u'\u010d', u'\u0159', u'\u017e', u'\xfd', u'\xe1', u'\xed', u'\xe9', u'OK']] self.shiftkeys_list = [[u'EXIT', u'!', u'"', u'\xa7', u'$', u'%', u'&', u'/', u'(', u')', u'=', u'BACKSPACE'], [u'Q', u'W', u'E', u'R', u'T', u'Z', u'U', u'I', u'O', u'P', u'\u0165', u'*'], [u'A', u'S', u'D', u'F', u'G', u'H', u'J', u'K', u'L', u'\u0148', u'\u010f', u"'"], [u'>', u'Y', u'X', u'C', u'V', u'B', u'N', u'M', u';', u':', u'_', u'CLEAR'], [u'SHIFT', u'SPACE', u'?', u'\\', u'\u010c', u'\u0158', u'\u0160', u'\u017d', u'\xda', u'\xc1', u'\xc9', u'OK']] self.nextLang = 'el_GR' elif self.lang == 'el_GR': self.keys_list = [[u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE'], [u'=', u'\u03c2', u'\u03b5', u'\u03c1', u'\u03c4', u'\u03c5', u'\u03b8', u'\u03b9', u'\u03bf', u'\u03c0', u'[', u']'], [u'\u03b1', u'\u03c3', u'\u03b4', u'\u03c6', u'\u03b3', u'\u03b7', u'\u03be', u'\u03ba', u'\u03bb', u';', u"'", u'-'], [u'\\', u'\u03b6', u'\u03c7', u'\u03c8', u'\u03c9', u'\u03b2', u'\u03bd', u'\u03bc', u',', '.', u'/', u'ALL'], [u'SHIFT', u'SPACE', u'\u03ac', u'\u03ad', u'\u03ae', u'\u03af', u'\u03cc', u'\u03cd', u'\u03ce', u'\u03ca', u'\u03cb', u'OK']] self.shiftkeys_list = [[u'EXIT', u'!', u'@', u'#', u'$', u'%', u'^', u'&', u'*', u'(', u')', u'BACKSPACE'], [u'+', u'\u20ac', u'\u0395', u'\u03a1', u'\u03a4', u'\u03a5', u'\u0398', u'\u0399', u'\u039f', u'\u03a0', u'{', u'}'], [u'\u0391', u'\u03a3', u'\u0394', u'\u03a6', u'\u0393', u'\u0397', u'\u039e', u'\u039a', u'\u039b', u':', u'"', u'_'], [u'|', u'\u0396', u'\u03a7', u'\u03a8', u'\u03a9', u'\u0392', u'\u039d', u'\u039c', u'<', u'>', u'?', u'CLEAR'], [u'SHIFT', u'SPACE', u'\u0386', u'\u0388', u'\u0389', u'\u038a', u'\u038c', u'\u038e', u'\u038f', u'\u03aa', u'\u03ab', u'OK']] self.nextLang = 'pl_PL' elif self.lang == 'pl_PL': self.keys_list = [[u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE'], [u'q', u'w', u'e', u'r', u't', u'y', u'u', u'i', u'o', u'p', u'-', u'['], [u'a', u's', u'd', u'f', u'g', u'h', u'j', u'k', u'l', u';', u"'", u'\\'], [u'<', u'z', u'x', u'c', u'v', u'b', u'n', u'm', u',', '.', u'/', u'ALL'], [u'SHIFT', u'SPACE', u'\u0105', u'\u0107', u'\u0119', u'\u0142', u'\u0144', u'\xf3', u'\u015b', u'\u017a', u'\u017c', u'OK']] self.shiftkeys_list = [[u'EXIT', u'!', u'@', u'#', u'$', u'%', u'^', u'&', u'(', u')', u'=', u'BACKSPACE'], [u'Q', u'W', u'E', u'R', u'T', u'Y', u'U', u'I', u'O', u'P', u'*', u']'], [u'A', u'S', u'D', u'F', u'G', u'H', u'J', u'K', u'L', u'?', u'"', u'|'], [u'>', u'Z', u'X', u'C', u'V', u'B', u'N', u'M', u';', u':', u'_', u'CLEAR'], [u'SHIFT', u'SPACE', u'\u0104', u'\u0106', u'\u0118', u'\u0141', u'\u0143', u'\xd3', u'\u015a', u'\u0179', u'\u017b', u'OK']] self.nextLang = 'en_EN' else: self.keys_list = [[u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE'], [u'q', u'w', u'e', u'r', u't', u'y', u'u', u'i', u'o', u'p', u'-', u'['], [u'a', u's', u'd', u'f', u'g', u'h', u'j', u'k', u'l', u';', u"'", u'\\'], [u'<', u'z', u'x', u'c', u'v', u'b', u'n', u'm', u',', '.', u'/', u'ALL'], [u'SHIFT', u'SPACE', u'OK', u'LEFT', u'RIGHT', u'*']] self.shiftkeys_list = [[u'EXIT', u'!', u'@', u'#', u'$', u'%', u'^', u'&', u'(', u')', u'=', u'BACKSPACE'], [u'Q', u'W', u'E', u'R', u'T', u'Y', u'U', u'I', u'O', u'P', u'+', u']'], [u'A', u'S', u'D', u'F', u'G', u'H', u'J', u'K', u'L', u'?', u'"', u'|'], [u'>', u'Z', u'X', u'C', u'V', u'B', u'N', u'M', u';', u':', u'_', u'CLEAR'], [u'SHIFT', u'SPACE', u'OK', u'LEFT', u'RIGHT', u'~']] self.lang = 'en_EN' self.nextLang = 'de_DE' self['country'].setText(self.lang) self.max_key = 47 + len(self.keys_list[4]) def virtualKeyBoardEntryComponent(self, keys): w, h = skin.parameters.get('VirtualKeyboard', (45, 45)) key_bg_width = self.key_bg and self.key_bg.size().width() or w key_images = self.shiftMode and self.keyImagesShift or self.keyImages res = [keys] text = [] x = 0 for key in keys: png = key_images.get(key, None) if png: width = png.size().width() res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, h), png=png)) else: width = key_bg_width res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, h), png=self.key_bg)) text.append(MultiContentEntryText(pos=(x, 0), size=(width, h), font=0, text=key.encode('utf-8'), flags=RT_HALIGN_CENTER | RT_VALIGN_CENTER)) x += width return res + text def buildVirtualKeyBoard(self): self.previousSelectedKey = None self.list = [] for keys in self.shiftMode and self.shiftkeys_list or self.keys_list: self.list.append(self.virtualKeyBoardEntryComponent(keys)) self.markSelectedKey() return def markSelectedKey(self): w, h = skin.parameters.get('VirtualKeyboard', (45, 45)) if self.previousSelectedKey is not None: self.list[self.previousSelectedKey / 12] = self.list[self.previousSelectedKey / 12][:-1] width = self.key_sel.size().width() x = self.list[self.selectedKey / 12][self.selectedKey % 12 + 1][1] self.list[self.selectedKey / 12].append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, h), png=self.key_sel)) self.previousSelectedKey = self.selectedKey self['list'].setList(self.list) return def backClicked(self): self['text'].deleteBackward() def forwardClicked(self): self['text'].deleteForward() def shiftClicked(self): self.smsChar = None self.shiftMode = not self.shiftMode self.buildVirtualKeyBoard() return def okClicked(self): self.smsChar = None text = (self.shiftMode and self.shiftkeys_list or self.keys_list)[self.selectedKey / 12][self.selectedKey % 12].encode('UTF-8') if text == 'EXIT': self.close(None) elif text == 'BACKSPACE': self['text'].deleteBackward() elif text == 'ALL': self['text'].markAll() elif text == 'CLEAR': self['text'].deleteAllChars() self['text'].update() elif text == 'SHIFT': self.shiftClicked() elif text == 'SPACE': self['text'].char(' '.encode('UTF-8')) elif text == 'OK': self.close(self['text'].getText()) elif text == 'LEFT': self['text'].left() elif text == 'RIGHT': self['text'].right() else: self['text'].char(text) return def okLongClicked(self): self.smsChar = None text = (self.shiftMode and self.shiftkeys_list or self.keys_list)[self.selectedKey / 12][self.selectedKey % 12].encode('UTF-8') if text == 'BACKSPACE': self['text'].deleteAllChars() self['text'].update() return def ok(self): self.close(self['text'].getText()) def exit(self): self.close(None) return def cursorRight(self): self['text'].right() def cursorLeft(self): self['text'].left() def left(self): self.smsChar = None self.selectedKey = self.selectedKey / 12 * 12 + (self.selectedKey + 11) % 12 if self.selectedKey > self.max_key: self.selectedKey = self.max_key self.markSelectedKey() return def right(self): self.smsChar = None self.selectedKey = self.selectedKey / 12 * 12 + (self.selectedKey + 1) % 12 if self.selectedKey > self.max_key: self.selectedKey = self.selectedKey / 12 * 12 self.markSelectedKey() return def up(self): self.smsChar = None self.selectedKey -= 12 if self.selectedKey < 0: self.selectedKey = self.max_key / 12 * 12 + self.selectedKey % 12 if self.selectedKey > self.max_key: self.selectedKey -= 12 self.markSelectedKey() return def down(self): self.smsChar = None self.selectedKey += 12 if self.selectedKey > self.max_key: self.selectedKey %= 12 self.markSelectedKey() return def keyNumberGlobal(self, number): self.smsChar = self.sms.getKey(number) self.selectAsciiKey(self.smsChar) def smsOK(self): if self.smsChar and self.selectAsciiKey(self.smsChar): print 'pressing ok now' self.okClicked() def keyGotAscii(self): self.smsChar = None if self.selectAsciiKey(str(unichr(getPrevAsciiCode()).encode('utf-8'))): self.okClicked() return def selectAsciiKey(self, char): if char == ' ': char = 'SPACE' for keyslist in (self.shiftkeys_list, self.keys_list): selkey = 0 for keys in keyslist: for key in keys: if key == char: self.selectedKey = selkey if self.shiftMode != (keyslist is self.shiftkeys_list): self.shiftMode = not self.shiftMode self.buildVirtualKeyBoard() else: self.markSelectedKey() return True selkey += 1 return False
class VirtualKeyBoard(Screen, HelpableScreen): def __init__(self, session, title=_("Virtual KeyBoard Text:"), text="", maxSize=False, visible_width=False, type=Input.TEXT, currPos=0, allMarked=False): Screen.__init__(self, session) HelpableScreen.__init__(self) self.setTitle(_("Virtual keyboard")) prompt = title # Title should only be used for screen titles! self.key_bg = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_bg.png")) self.key_sel = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_sel.png")) self.key_longl_sel = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_longl_sel.png")) self.key_longm_sel = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_longm_sel.png")) self.key_longr_sel = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_longr_sel.png")) key_longl_bg = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_longl_bg.png")) key_longm_bg = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_longm_bg.png")) key_longr_bg = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_longr_bg.png")) key_red_bg = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_red.png")) key_green_bg = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_green.png")) key_yellow_bg = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_yellow.png")) key_blue_bg = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_blue.png")) key_backspace = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_backspace.png")) key_enter = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_enter.png")) key_first = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_first.png")) key_last = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_last.png")) key_left = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_left.png")) key_right = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_right.png")) key_shift0 = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_shift0.png")) key_shift1 = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_shift1.png")) key_shift2 = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_shift2.png")) key_shift3 = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_shift3.png")) # self.key_space = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_space.png")) key_space_alt = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_space_alt.png")) self.key_sel_width = self.key_sel.size().width() self.keyBackgrounds = { "EXIT": key_red_bg, "OK": key_green_bg, "ENTER": key_green_bg, "LOC": key_yellow_bg, "SHFT": key_blue_bg, "LongL": key_longl_bg, "LongM": key_longm_bg, "LongR": key_longr_bg } self.keyImages = [{ "BACKSPACE": key_backspace, "ENTER": key_enter, "FIRST": key_first, "LAST": key_last, "LEFT": key_left, "RIGHT": key_right, "SHIFT": key_shift0, "SPACE": key_space_alt }, { "BACKSPACE": key_backspace, "ENTER": key_enter, "FIRST": key_first, "LAST": key_last, "LEFT": key_left, "RIGHT": key_right, "SHIFT": key_shift1, "SPACE": key_space_alt }, { "BACKSPACE": key_backspace, "ENTER": key_enter, "FIRST": key_first, "LAST": key_last, "LEFT": key_left, "RIGHT": key_right, "SHIFT": key_shift2, "SPACE": key_space_alt }, { "BACKSPACE": key_backspace, "ENTER": key_enter, "FIRST": key_first, "LAST": key_last, "LEFT": key_left, "RIGHT": key_right, "SHIFT": key_shift3, "SPACE": key_space_alt }] self.shiftMsgs = [ _("Lower case"), _("Upper case"), _("Special 1"), _("Special 2") ] self.english = [ [ [u"`", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"-", u"=", u"BACKSPACE"], [u"FIRST", u"q", u"w", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"[", u"]", u"\\"], [u"LAST", u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u";", u"'", u"", u"ENTER"], [u"SHIFT", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", u".", u"/", u"", u"", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ], [ [u"~", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"*", u"(", u")", u"_", u"+", u"BACKSPACE"], [u"FIRST", u"Q", u"W", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"{", u"}", u"|"], [u"LAST", u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u":", u"\"", u"", u"ENTER"], [u"SHIFT", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u"<", u">", u"?", u"", u"", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ] ] self.english_EN_US = [ [ [u"`", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"-", u"=", u"BACKSPACE"], [u"FIRST", u"q", u"w", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"[", u"]", u"\\"], [u"LAST", u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u";", u"'", u"LongL__ENTER__HIDE", u"LongR__Enter"], [u"LongL__Shift", u"LongR__SHIFT__HIDE", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", u".", u"/", u"LongL__SHIFT__HIDE", u"LongR__Shift"], [u"LongL__Esc", u"LongR__ESC__HIDE", u"Loc", u"All", u"LongL__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongR__SPACE__HIDE", u"LEFT", u"RIGHT", u"LongL__CLR__HIDE", u"LongR__Clr"] ], [ [u"~", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"*", u"(", u")", u"_", u"+", u"BACKSPACE"], [u"FIRST", u"Q", u"W", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"{", u"}", u"|"], [u"LAST", u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u":", u"\"", u"LongL__ENTER__HIDE", u"LongR__Enter"], [u"LongL__Shift", u"LongR__SHIFT__HIDE", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u"<", u">", u"?", u"LongL__SHIFT__HIDE", u"LongR__Shift"], [u"LongL__Esc", u"LongR__ESC__HIDE", u"Loc", u"All", u"LongL__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongR__SPACE__HIDE", u"LEFT", u"RIGHT", u"LongL__CLR__HIDE", u"LongR__Clr"] ] ] self.french = [ [ [u"\u00B2", u"&", u"\u00E9", u"\"", u"'", u"(", u"-", u"\u00E8", u"_", u"\u00E7", u"\u00E0", u")", u"=", u"BACKSPACE"], [u"FIRST", u"a", u"z", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"$", u"[", u"]"], [u"LAST", u"q", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"m", u"\u00F9", u"*", u"ENTER"], [u"SHIFT", u"<", u"w", u"x", u"c", u"v", u"b", u"n", u",", u";", u":", u"!", u"\u20AC", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE", u"#", u"@", u"`"] ], [ [u"", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"\u00B0", u"+", u"BACKSPACE"], [u"FIRST", u"A", u"Z", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"\u00A3", u"{", u"}"], [u"LAST", u"Q", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"M", u"%", u"\u00B5", u"ENTER"], [u"SHIFT", u">", u"W", u"X", u"C", u"V", u"B", u"N", u"?", u".", u"/", u"\u00A7", u"\u00A6", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE", u"~", u"^", u"\\"] ], [ [u"", u"", u"\u00E2", u"\u00EA", u"\u00EE", u"\u00F4", u"\u00FB", u"\u00E4", u"\u00EB", u"\u00EF", u"\u00F6", u"\u00FC", u"", u"BACKSPACE"], [u"FIRST", u"", u"\u00E0", u"\u00E8", u"\u00EC", u"\u00F2", u"\u00F9", u"\u00E1", u"\u00E9", u"\u00ED", u"\u00F3", u"\u00FA", u"", u""], [u"LAST", u"", u"\u00C2", u"\u00CA", u"\u00CE", u"\u00D4", u"\u00DB", u"\u00C4", u"\u00CB", u"\u00CF", u"\u00D6", u"\u00DC", u"", u"ENTER"], [u"SHIFT", u"", u"\u00C0", u"\u00C8", u"\u00CC", u"\u00D2", u"\u00D9", u"\u00C1", u"\u00C9", u"\u00CD", u"\u00D3", u"\u00DA", u"", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ] ] self.german = [ [ [u"", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"\u00DF", u"'", u"BACKSPACE"], [u"FIRST", u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"\u00FC", u"[", u"]"], [u"LAST", u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"\u00F6", u"\u00E4", u"+", U"ENTER"], [u"SHIFT", u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"#", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE", u"|", u"\\", u"\u00B5"] ], [ [u"\u00B0", u"!", u"\"", u"\u00A7", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"?", u"`", u"BACKSPACE"], [u"FIRST", u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"\u00DC", u"{", u"}"], [u"LAST", u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"\u00D6", u"\u00C4", u"*", U"ENTER"], [u"SHIFT", u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"@", U"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE", u"\u20AC", u"\u00B2", u"\u00B3"] ] ] self.latvian = [ [ [u"`", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"-", u"=", u"BACKSPACE"], [u"FIRST", u"q", u"w", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"[", u"]", u"\\"], [u"LAST", u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u";", u"'", u"LongL__ENTER__HIDE", u"LongR__Enter"], [u"LongL__Shift", u"LongR__SHIFT__HIDE", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", u".", u"/", u"LongL__SHIFT__HIDE", u"LongR__Shift"], [u"LongL__Esc", u"LongR__ESC__HIDE", u"Loc", u"All", u"LongL__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongR__SPACE__HIDE", u"LEFT", u"RIGHT", u"LongL__CLR__HIDE", u"LongR__Clr"] ], [ [u"~", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"*", u"(", u")", u"_", u"+", u"BACKSPACE"], [u"FIRST", u"Q", u"W", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"{", u"}", u"|"], [u"LAST", u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u":", u"\"", u"LongL__ENTER__HIDE", u"LongR__Enter"], [u"LongL__Shift", u"LongR__SHIFT__HIDE", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u"<", u">", u"?", u"LongL__SHIFT__HIDE", u"LongR__Shift"], [u"LongL__Esc", u"LongR__ESC__HIDE", u"Loc", u"All", u"LongL__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongR__SPACE__HIDE", u"LEFT", u"RIGHT", u"LongL__CLR__HIDE", u"LongR__Clr"] ], [ [u"\u00b4", u"\u00b9", u"\u00b2", u"\u00b3", u"\u20ac", u"\u00bd", u"\u00be", u"\u007b", u"\u005b", u"\u005d", u"\u007d ", u"\u005c", u"\u2013", u"BACKSPACE"], [u"FIRST", u"q", u"\u0113", u"\u0112", u"\u0157", u"\u0156", u"\u016B", u"\u016A", u"\u012B", u"\u012A", u"\u014D", u"\u014C", u"\u00ab", u"\u00bb"], [u"LAST", u"\u0101", u"\u0100", u"\u0161", u"\u0160", u"\u0123", u"\u0122", u"\u0137", u"\u0136", u"\u013C", u"\u013B", u"\u003b", u"LongL__ENTER__HIDE", u"LongR__Enter"], [u"LongL__Shift", u"LongR__SHIFT__HIDE", u"\u017E", u"\u017D", u"\u010D", u"\u010C", u"b", u"\u0146", u"\u0145", u"\u0060", u"\u00b7", u"\u002f", u"LongL__SHIFT__HIDE", u"LongR__Shift"], [u"LongL__Esc", u"LongR__ESC__HIDE", u"Loc", u"All", u"LongL__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongR__SPACE__HIDE", u"LEFT", u"RIGHT", u"LongL__CLR__HIDE", u"LongR__Clr"] ] ] self.russian = [ [ [u"\u0451", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"-", u"=", u"BACKSPACE"], [u"FIRST", u"\u0439", u"\u0446", u"\u0443", u"\u043A", u"\u0435", u"\u043D", u"\u0433", u"\u0448", u"\u0449", u"\u0437", u"\u0445", u"\u044A", u"\u00A7"], [u"LAST", u"\u0444", u"\u044B", u"\u0432", u"\u0430", u"\u043F", u"\u0440", u"\u043E", u"\u043B", u"\u0434", u"\u0436", u"\u044D", u"\\", u"ENTER"], [u"SHIFT", u"\u044F", u"\u0447", u"\u0441", u"\u043C", u"\u0438", u"\u0442", u"\u044C", u"\u0431", u"\u044E", u".", u"@", u"&", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE", u"<"] ], [ [u"\u0401", u"!", u"\"", u"\u2116", u";", u"%", u":", u"?", u"*", u"(", u")", u"_", u"+", u"BACKSPACE"], [u"FIRST", u"\u0419", u"\u0426", u"\u0423", u"\u041A", u"\u0415", u"\u041D", u"\u0413", u"\u0428", u"\u0429", u"\u0417", u"\u0425", u"\u042A", u"\u20BD"], [u"LAST", u"\u0424", u"\u042B", u"\u0412", u"\u0410", u"\u041F", u"\u0420", u"\u041E", u"\u041B", u"\u0414", u"\u0416", u"\u042D", u"/", u"ENTER"], [u"SHIFT", u"\u042F", u"\u0427", u"\u0421", u"\u041C", u"\u0418", u"\u0422", u"\u042C", u"\u0411", u"\u042E", u",", u"#", u"$", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE", u">"] ] ] self.scandinavian = [ [ [u"\u00A7", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"+", u"@", u"BACKSPACE"], [u"FIRST", u"q", u"w", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"\u00E5", u"[", u"]"], [u"LAST", u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"\u00F6", u"\u00E4", u"'", u"ENTER"], [u"SHIFT", u"<", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"\u00AB", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ], [ [u"\u00BD", u"!", u"\"", u"#", u"\u00A4", u"%", u"&", u"/", u"(", u")", u"=", u"?", u"|", u"BACKSPACE"], [u"FIRST", u"Q", u"W", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"\u00C5", u"{", u"}"], [u"LAST", u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"\u00D6", u"\u00C4", u"*", u"ENTER"], [u"SHIFT", u">", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"\u00BB", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ], [ [u"", u"\u00E2", u"\u00EA", u"\u00EE", u"\u00F4", u"\u00FB", u"\u00E4", u"\u00EB", u"\u00EF", u"\u00F6", u"\u00FC", u"\u00E3", u"\u00F5", u"BACKSPACE"], [u"FIRST", u"\u00E0", u"\u00E8", u"\u00EC", u"\u00F2", u"\u00F9", u"\u00E1", u"\u00E9", u"\u00ED", u"\u00F3", u"\u00FA", u"", u"", u""], [u"LAST", u"\u00C2", u"\u00CA", u"\u00CE", u"\u00D4", u"\u00DB", u"\u00C4", u"\u00CB", u"\u00CF", u"\u00D6", u"\u00DC", u"\u00C3", u"\u00D5", u"ENTER"], [u"SHIFT", u"\u00C0", u"\u00C8", u"\u00CC", u"\u00D2", u"\u00D9", u"\u00C1", u"\u00C9", u"\u00CD", u"\u00D3", u"\u00DA", u"", u"", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ] ] self.spanish = [ [ [u"\\", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"'", u"\u00A1", u"BACKSPACE"], [u"FIRST", u"q", u"w", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"@", u"+", u"\u00E7"], [u"LAST", u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"\u00F1", u"[", u"]", u"ENTER"], [u"SHIFT", u"<", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"\u20AC", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE", u"", u"\u00E1", u"\u00E9", u"\u00ED", u"\u00F3", u"\u00FA", u"\u00FC"] ], [ [u"|", u"!", u"\"", u"\u00B7", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"?", u"\u00BF", u"BACKSPACE"], [u"FIRST", u"Q", u"W", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"#", u"*", u"\u00C7"], [u"LAST", u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"\u00D1", u"{", u"}", u"ENTER"], [u"SHIFT", u">", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"\u00AC", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE", u"", u"\u00C1", u"\u00C9", u"\u00CD", u"\u00D3", u"\u00DA", u"\u00DC"] ] ] self.locales = { "ar_BH": [_("Arabic"), _("Bahrain"), self.arabic(self.english)], "ar_EG": [_("Arabic"), _("Egypt"), self.arabic(self.english)], "ar_JO": [_("Arabic"), _("Jordan"), self.arabic(self.english)], "ar_KW": [_("Arabic"), _("Kuwait"), self.arabic(self.english)], "ar_LB": [_("Arabic"), _("Lebanon"), self.arabic(self.english)], "ar_OM": [_("Arabic"), _("Oman"), self.arabic(self.english)], "ar_QA": [_("Arabic"), _("Qatar"), self.arabic(self.english)], "ar_SA": [_("Arabic"), _("Saudi Arabia"), self.arabic(self.english)], "ar_SY": [_("Arabic"), _("Syrian Arab Republic"), self.arabic(self.english)], "ar_AE": [_("Arabic"), _("United Arab Emirates"), self.arabic(self.english)], "ar_YE": [_("Arabic"), _("Yemen"), self.arabic(self.english)], "cs_CZ": [_("Czech"), _("Czechia"), [ [ [u";", u"+", u"\u011B", u"\u0161", u"\u010D", u"\u0159", u"\u017E", u"\u00FD", u"\u00E1", u"\u00ED", u"\u00E9", u"=", u"", u"BACKSPACE"], [u"FIRST", u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"\u00FA", u")", u""], [u"LAST", u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"\u016F", u"\u00A7", u"", u"ENTER"], [u"SHIFT", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"\u0148", u"", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"LongL__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongR__SPACE__HIDE", u"ALL", u"CLR", u"DEL"] ], [ [u".", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"%", u"", u"BACKSPACE"], [u"FIRST", u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"/", u"(", u""], [u"LAST", u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"\"", u"!", u"'", u"ENTER"], [u"SHIFT", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u"?", u":", u"_", u"\u0147", u"", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"LongL__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongR__SPACE__HIDE", u"ALL", u"CLR", u"DEL"] ], [ [u"", u"~", u"\u011A", u"\u0160", u"\u010C", u"\u0158", u"\u017D", u"\u00DD", u"\u00C1", u"\u00CD", u"\u00C9", u"`", u"", u"BACKSPACE"], [u"FIRST", u"\\", u"|", u"\u20AC", u"\u0165", u"\u0164", u"", u"", u"", u"\u00F3", u"\u00D3", u"\u00DA", u"\u00F7", u"\u00D7"], [u"LAST", u"", u"\u0111", u"\u00D0", u"[", u"]", u"\u010F", u"\u010E", u"\u0142", u"\u0141", u"\u016E", u"$", u"\u00DF", u"ENTER"], [u"SHIFT", u"", u"#", u"&", u"@", u"{", u"}", u"", u"<", u">", u"*", u"", u"\u00A4", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"LongL__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongM__SPACE__HIDE", u"LongR__SPACE__HIDE", u"ALL", u"CLR", u"DEL"] ] ]], "nl_NL": [_("Dutch"), _("Netherlands"), self.dutch(self.english)], "en_AU": [_("English"), _("Australian"), self.australian(self.english)], "en_GB": [_("English"), _("United Kingdom"), self.unitedKingdom(self.english)], "en_US": [_("English"), _("United States"), self.english_EN_US], "en_EN": [_("English"), _("Various"), self.english_EN_US], "et_EE": [_("Estonian"), _("Estonia"), self.estonian(self.scandinavian)], "fi_FI": [_("Finnish"), _("Finland"), self.finnish(self.scandinavian)], "fr_BE": [_("French"), _("Belgian"), self.belgian(self.french)], "fr_FR": [_("French"), _("France"), self.french], "de_CH": [_("German"), _("Switzerland"), self.swiss(self.german)], "de_DE": [_("German"), _("Germany"), self.german], "el_GR": [_("Greek (Modern)"), _("Greece"), [ [ [u"`", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"-", u"=", u"BACKSPACE"], [u"FIRST", u";", u"\u03C2", u"\u03B5", u"\u03C1", u"\u03C4", u"\u03C5", u"\u03B8", u"\u03B9", u"\u03BF", u"\u03C0", u"[", u"]", u"/"], [u"LAST", u"\u03B1", u"\u03C3", u"\u03B4", u"\u03C6", u"\u03B3", u"\u03B7", u"\u03BE", u"\u03BA", u"\u03BB", u"", u"'", u"\\", u"ENTER"], [u"SHIFT", u"<", u"\u03B6", u"\u03C7", u"\u03C8", u"\u03C9", u"\u03B2", u"\u03BD", u"\u03BC", u",", ".", u"\u03CA", u"\u03CB", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE", u"\u03AC", u"\u03AD", u"\u03AE", u"\u03AF", u"\u03CC", u"\u03CD", u"\u03CE"] ], [ [u"~", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"*", u"(", u")", u"_", u"+", u"BACKSPACE"], [u"FIRST", u":", u"", u"\u0395", u"\u03A1", u"\u03A4", u"\u03A5", u"\u0398", u"\u0399", u"\u039F", u"\u03A0", u"{", u"}", u"?"], [u"LAST", u"\u0391", u"\u03A3", u"\u0394", u"\u03A6", u"\u0393", u"\u0397", u"\u039E", u"\u039A", u"\u039B", u"", u"\"", u"|", u"ENTER"], [u"SHIFT", u">", u"\u0396", u"\u03A7", u"\u03A8", u"\u03A9", u"\u0392", u"\u039D", u"\u039C", u"<", u">", u"\u03AA", u"\u03AB", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE", u"\u0386", u"\u0388", u"\u0389", u"\u038A", u"\u038C", u"\u038E", u"\u038F"] ], [ [u"", u"", u"\u00B2", u"\u00B3", u"\u00A3", u"\u00A7", u"\u00B6", u"\u20AC", u"\u00A4", u"\u00A6", u"\u00B0", u"\u00B1", u"\u00BD", u"BACKSPACE"], [u"FIRST", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"", u""], [u"LAST", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"ENTER"], [u"SHIFT", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ] ]], "lv_LV": [_("Latvian"), _("Latvia"), self.latvian], "lt_LT": [_("Lithuanian"), _("Lithuania"), self.lithuanian(self.english)], "nb_NO": [_("Norwegian"), _("Norway"), self.norwegian(self.scandinavian)], "fa_IR": [_("Persian"), _("Iran, Islamic Republic"), self.persian(self.english)], "pl_PL": [_("Polish"), _("Poland"), self.polish(self.english)], "ru_RU": [_("Russian"), _("Russian Federation"), self.russian], "sk_SK": [_("Slovak"), _("Slovakia"), [ [ [u"~", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"*", u"(", u")", u"\u00E1", u"\u00E4", u"BACKSPACE"], [u"FIRST", u"q", u"w", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"\u010D", u"\u010F", u"\u00E9"], [u"LAST", u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"\u00ED", u"\u013A", u"\u013E", u"ENTER"], [u"SHIFT", u"<", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"\u0148", u"\u00F3", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE", u"\u00F4", u"\u0155", u"\u0161", u"\u0165", u"\u00FA", u"\u00FD", u"\u017E"] ], [ [u"`", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"\u00C1", u"\u00C4", u"BACKSPACE"], [u"FIRST", u"Q", u"W", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"\u010C", u"\u010E", u"\u00C9"], [u"LAST", u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"\u00CD", u"\u0139", u"\u013D", u"ENTER"], [u"SHIFT", u">", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u"?", u":", u"\u0147", u"\u00D3", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE", u"\u00D4", u"\u0154", u"\u0160", u"\u0164", u"\u00DA", u"\u00DD", u"\u017D"] ], [ [u"", u"", u"\u00A7", u"\u00B0", u"\u00A4", u"\u20AC", u"\u00DF", u"\u0111", u"\u0110", u"\u0142", u"\u0141", u"", u"", u"BACKSPACE"], [u"FIRST", u"", u"", u"'", u"\"", u"+", u"-", u"\u00D7", u"\u00F7", u"=", u"_", u"~", u"", u""], [u"LAST", u"", u"", u"/", u"\\", u";", u"[", u"]", u"{", u"}", u"|", u"", u"", u"ENTER"], [u"SHIFT", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ] ]], "es_ES": [_("Spanish"), _("Spain"), self.spanish], "sv_SE": [_("Swedish"), _("Sweden"), self.swedish(self.scandinavian)], "th_TH": [_("Thai"), _("Thailand"), [ [ [u"", u"", u"\u0E45", u"\u0E20", u"\u0E16", u"\u0E38", u"\u0E36", u"\u0E04", u"\u0E15", u"\u0E08", u"\u0E02", u"\u0E0A", u"", u"BACKSPACE"], [u"FIRST", u"\u0E46", u"\u0E44", u"\u0E33", u"\u0E1E", u"\u0E30", u"\u0E31", u"\u0E35", u"\u0E23", u"\u0E19", u"\u0E22", u"\u0E1A", u"\u0E25", u""], [u"LAST", u"\u0E1F", u"\u0E2B", u"\u0E01", u"\u0E14", u"\u0E40", u"\u0E49", u"\u0E48", u"\u0E32", u"\u0E2A", u"\u0E27", u"\u0E07", u"\u0E03", u"OK"], [u"SHIFT", u"\u0E1C", u"\u0E1B", u"\u0E41", u"\u0E2D", u"\u0E34", u"\u0E37", u"\u0E17", u"\u0E21", u"\u0E43", u"\u0E1D", u"", u"", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ], [ [u"", u"", u"\u0E51", u"\u0E52", u"\u0E53", u"\u0E54", u"\u0E39", u"\u0E55", u"\u0E56", u"\u0E57", u"\u0E58", u"\u0E59", u"", u"BACKSPACE"], [u"FIRST", u"\u0E50", u"", u"\u0E0E", u"\u0E11", u"\u0E18", u"\u0E4D", u"\u0E4A", u"\u0E13", u"\u0E2F", u"\u0E0D", u"\u0E10", u"\u0E05", u""], [u"LAST", u"\u0E24", u"\u0E06", u"\u0E0F", u"\u0E42", u"\u0E0C", u"\u0E47", u"\u0E4B", u"\u0E29", u"\u0E28", u"\u0E0B", u"", u"\u0E3F", u"OK"], [u"SHIFT", u"", u"", u"\u0E09", u"\u0E2E", u"\u0E3A", u"\u0E4C", u"", u"\u0E12", u"\u0E2C", u"\u0E26", u"", u"", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ] ]], "uk_UA": [_("Ukrainian"), _("Ukraine"), self.ukranian(self.russian)] } self["actions"] = HelpableNumberActionMap(self, "VirtualKeyBoardActions", { "cancel": (self.cancel, _("Cancel any text changes and exit")), "save": (self.enter, _("Enter text and exit")), "locale": (self.localeMenu, _("Select the virtual keyboard locale from a menu")), "shift": (self.shiftClicked, _("Select the virtual keyboard shifted character set")), "select": (self.processSelect, _("Select the character or action under the virtual keyboard cursor")), "up": (self.up, _("Move the virtual keyboard cursor up")), "left": (self.left, _("Move the virtual keyboard cursor left")), "right": (self.right, _("Move the virtual keyboard cursor right")), "down": (self.down, _("Move the virtual keyboard cursor down")), "first": (self.cursorFirst, _("Move the text buffer cursor to the first character")), "prev": (self.cursorLeft, _("Move the text buffer cursor left")), "next": (self.cursorRight, _("Move the text buffer cursor right")), "last": (self.cursorLast, _("Move the text buffer cursor to the last character")), "toggleOverwrite": (self.keyToggleOW, _("Toggle new text inserts before or overwrites existing text")), "backspace": (self.backClicked, _("Delete the character to the left of text buffer cursor")), "delete": (self.forwardClicked, _("Delete the character under the text buffer cursor")), "1": (self.keyNumberGlobal, _("Number or SMS style data entry")), "2": (self.keyNumberGlobal, _("Number or SMS style data entry")), "3": (self.keyNumberGlobal, _("Number or SMS style data entry")), "4": (self.keyNumberGlobal, _("Number or SMS style data entry")), "5": (self.keyNumberGlobal, _("Number or SMS style data entry")), "6": (self.keyNumberGlobal, _("Number or SMS style data entry")), "7": (self.keyNumberGlobal, _("Number or SMS style data entry")), "8": (self.keyNumberGlobal, _("Number or SMS style data entry")), "9": (self.keyNumberGlobal, _("Number or SMS style data entry")), "0": (self.keyNumberGlobal, _("Number or SMS style data entry")), "gotAsciiCode": (self.keyGotAscii, _("Keyboard data entry")) }, -2, description=_("Virtual KeyBoard Functions")) self.lang = language.getLanguage() self["prompt"] = Label(prompt) self["text"] = Input(text=text, maxSize=maxSize, visible_width=visible_width, type=type, currPos=len(text.decode("utf-8", "ignore")), allMarked=allMarked) self["list"] = VirtualKeyBoardList([]) self["mode"] = Label(_("INS")) self["locale"] = Label(_("Locale") + ": " + self.lang) self["language"] = Label(_("Language") + ": " + self.lang) self["key_info"] = StaticText(_("INFO")) self["key_red"] = StaticText(_("Exit")) self["key_green"] = StaticText(_("Enter")) self["key_yellow"] = StaticText(_("Select locale")) self["key_blue"] = StaticText(self.shiftMsgs[1]) self["key_help"] = StaticText(_("HELP")) width, self.height = skin.parameters.get("VirtualKeyBoard", (45, 45)) self.width = self.key_bg and self.key_bg.size().width() or width self.shiftColors = skin.parameters.get("VirtualKeyBoardShiftColors", (0x00ffffff, 0x00ffffff, 0x0000ffff, 0x00ff00ff)) # Ensure there is a color for each shift level! self.language = None self.location = None self.keyList = [] self.previousSelectedKey = [] self.shiftLevels = 0 self.shiftLevel = 0 self.keyboardWidth = 0 self.keyboardHeight = 0 self.maxKey = 0 self.overwrite = False self.selectedKey = None self.sms = NumericalTextInput(self.smsGotChar) self.smsChar = None self.setLocale() self.onExecBegin.append(self.setKeyboardModeAscii) self.onLayoutFinish.append(self.buildVirtualKeyBoard) def arabic(self, base): keyList = copy.deepcopy(base) keyList[1][0][8] = u"\u066D" keyList.extend([[ [u"\u0630", u"\u0661", u"\u0662", u"\u0663", u"\u0664", u"\u0665", u"\u0666", u"\u0667", u"\u0668", u"\u0669", u"\u0660", u"-", u"=", u"BACKSPACE"], [u"FIRST", u"\u0636", u"\u0635", u"\u062B", u"\u0642", u"\u0641", u"\u063A", u"\u0639", u"\u0647", u"\u062E", u"\u062D", u"\u062C", u"\u062F", u"\\"], [u"LAST", u"\u0634", u"\u0633", u"\u064A", u"\u0628", u"\u0644", u"\u0627", u"\u062A", u"\u0646", u"\u0645", u"\u0643", u"\u0637", u"", u"ENTER"], [u"SHIFT", u"\u0626", u"\u0621", u"\u0624", u"\u0631", u"\uFEFB", u"\u0649", u"\u0629", u"\u0648", u"\u0632", u"\u0638", u"", u"", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ], [ [u"\u0651", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"\u066D", u"(", u")", u"_", u"+", u"BACKSPACE"], [u"FIRST", u"\u0636", u"\u0635", u"\u062B", u"\u0642", u"\u0641", u"\u063A", u"\u0639", u"\u00F7", u"\u00D7", u"\u061B", u">", u"<", u"|"], [u"LAST", u"\u0634", u"\u0633", u"\u064A", u"\u0628", u"\u0644", u"\u0623", u"\u0640", u"\u060C", u"/", u":", u"\"", u"", u"ENTER"], [u"SHIFT", u"\u0626", u"\u0621", u"\u0624", u"\u0631", u"\uFEF5", u"\u0622", u"\u0629", u",", u".", u"\u061F", u"", u"", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ]]) return keyList def australian(self, base): keyList = copy.deepcopy(base) keyList[0][-1].extend([u"www.", u".com", u".net", u".org", u".edu", u".au", u".tv"]) keyList[1][-1].extend([u"www.", u".com", u".net", u".org", u".edu", u".au", u".tv"]) return keyList def belgian(self, base): keyList = copy.deepcopy(base) keyList[0][0][6] = u"\u00A7" keyList[0][0][8] = u"!" keyList[0][0][12] = u"-" keyList[0][2][12] = u"\u00B5" keyList[0][3][11] = u"=" keyList[1][0][0] = u"\u00B3" keyList[1][0][12] = u"_" keyList[1][1][11] = u"*" keyList[1][2][12] = u"\u00A3" keyList[1][3][11] = u"+" return keyList def dutch(self, base): keyList = copy.deepcopy(base) keyList[0][0][0] = u"@" keyList[0][0][11] = u"/" keyList[0][0][12] = u"\u00BA" keyList[0][1][11] = u"\u00A8" keyList[0][1][12] = u"*" keyList[0][1][13] = u"<" keyList[0][2][10] = u"+" keyList[0][2][11] = u"\u00B4" keyList[0][2][12] = u"\\" keyList[0][3] = [u"SHIFT", u"]", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", u".", u"-", u"{", u"SHIFT"] keyList[0][-1].extend([u"www.", u".com", u".net", u".org", u".edu", u".nl", u".tv"]) keyList[1][0] = [u"\u00A7", u"!", u"\"", u"#", u"$", u"%", u"&", u"_", u"(", u")", u"'", u"?", u"~", u"BACKSPACE"] keyList[1][1][11] = u"^" keyList[1][1][12] = u"|" keyList[1][1][13] = u">" keyList[1][2][10] = u"\u00B1" keyList[1][2][11] = u"`" keyList[1][2][12] = u"\u00A6" keyList[1][3] = [u"SHIFT", u"[", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"=", u"}", u"SHIFT"] keyList[1][-1].extend([u"www.", u".com", u".net", u".org", u".edu", u".nl", u".tv"]) keyList.append([ [u"\u00AC", u"\u00B9", u"\u00B2", u"\u00B3", u"\u00BC", u"\u00BD", u"\u00BE", u"\u00A3", u"{", u"}", u"$", u"\\", u"", u"BACKSPACE"], [u"FIRST", u"", u"", u"\u20AC", u"\u00B6", u"", u"", u"", u"", u"", u"", u"", u"", u""], [u"LAST", u"", u"\u00E1", u"\u00E9", u"\u00ED", u"\u00F3", u"\u00FA", u"\u00C1", u"\u00C9", u"\u00CD", u"\u00D3", u"\u00DA", u"", u"ENTER"], [u"SHIFT", u"\u00A6", u"\u00AB", u"\u00BB", u"\u00A2", u"", u"", u"", u"\u00B5", u"", u"\u00B7", u"", u"", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ]) return keyList def estonian(self, base): keyList = copy.deepcopy(base) keyList[0][1][11] = u"\u00FC" keyList[0][1][12] = u"\u00F5" keyList[0][1][13] = u"\u0161" keyList[0][3][12] = u"\u017E" keyList[0][4].extend([u"[", u"]", u"\\"]) keyList[1][1][11] = u"\u00DC" keyList[1][1][12] = u"\u00D5" keyList[1][1][13] = u"\u0160" keyList[1][3][12] = u"\u017D" keyList[1][4].extend([u"{", u"}", u"\u00A3", u"$", u"\u20AC"]) del keyList[2] return keyList def finnish(self, base): keyList = copy.deepcopy(base) keyList[0][4].append(u"\\") keyList[1][4].extend([u"\u00A3", u"$", u"\u20AC"]) return keyList def lithuanian(self, base): keyList = copy.deepcopy(base) keyList[0][0] = [u"`", u"\u0105", u"\u010D", u"\u0119", u"\u0117", u"\u012F", u"\u0161", u"\u0173", u"\u016B", u"", u"", u"", u"\u017E", u"BACKSPACE"] keyList[0][1][13] = u"" keyList[0][2][12] = u"\\" keyList[1][0] = [u"~", u"\u0104", u"\u010C", u"\u0118", u"\u0116", u"\u012E", u"\u0160", u"\u0172", u"\u016A", u"\u201E", u"\u201C", u"", u"\u017D", u"BACKSPACE"] keyList[1][1][13] = u"" keyList[1][2][12] = u"|" keyList.append([ [u"\u02DC", u"\u00BC", u"\u00BD", u"\u00BE", u"\u00A4", u"\u00A2", u"\u00B0", u"\u00A7", u"\u00D7", u"\u00AB", u"\u00BB", u"\u00F7", u"\u00B1", u"BACKSPACE"], [u"FIRST", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"-", u"=", u"\u00AD"], [u"LAST", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"*", u"(", u")", u"_", u"+", u"ENTER"], [u"SHIFT", u"", u"\u00DF", u"\u00A9", u"\u00AE", u"\u2122", u"\u00AC", u"\u00A3", u"\u20AC", u"\u00B7", u"\u00B9", u"\u00B2", u"\u00B3", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ]) return keyList def norwegian(self, base): keyList = copy.deepcopy(base) keyList[0][0][0] = u"|" keyList[0][0][12] = u"\\" keyList[0][2][10] = u"\u00F8" keyList[0][2][11] = u"\u00E6" keyList[0][3][12] = u"\u00B5" keyList[1][0][0] = u"\u00A7" keyList[1][0][12] = u"@" keyList[1][2][10] = u"\u00D8" keyList[1][2][11] = u"\u00C6" keyList[1][3][12] = u"" keyList[1][4].extend([u"\u00A3", u"$", u"\u20AC"]) return keyList def persian(self, base): keyList = copy.deepcopy(base) keyList.append([ [u"\u00F7", u"\u06F1", u"\u06F2", u"\u06F3", u"\u06F4", u"\u06F5", u"\u06F6", u"\u06F7", u"\u06F8", u"\u06F9", u"\u06F0", u"-", u"=", u"BACKSPACE"], [u"FIRST", u"\u0636", u"\u0635", u"\u062B", u"\u0642", u"\u0641", u"\u063A", u"\u0639", u"\u0647", u"\u062E", u"\u062D", u"\u062C", u"\u0686", u"\u067E"], [u"LAST", u"\u0634", u"\u0633", u"\u0649", u"\u0628", u"\u0644", u"\u0622", u"\u0627", u"\u062A", u"\u0646", u"\u0645", u"\u06A9", u"\u06AF", u"ENTER"], [u"SHIFT", u"\u0638", u"\u0637", u"\u0698", u"\u0632", u"\u0631", u"\u0630", u"\u062F", u"\u0626", u"\u0621", u"\u0648", u"\u060C", u"\u061F", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ]) return keyList def polish(self, base): keyList = copy.deepcopy(base) keyList[0][3][11] = u"\u0105" keyList[0][3][12] = u"\u0107" keyList[0][-1].extend([u"\u0119", u"\u0142", u"\u0144", u"\u00F3", u"\u015B", u"\u017A", u"\u017C"]) keyList[1][2][12] = u"\u20AC" keyList[1][3][11] = u"\u0104" keyList[1][3][12] = u"\u0106" keyList[1][-1].extend([u"\u0118", u"\u0141", u"\u0143", u"\u00D3", u"\u015A", u"\u0179", u"\u017B"]) return keyList def swedish(self, base): keyList = copy.deepcopy(base) keyList[0][4].extend([u"\\", u"\u00B5"]) keyList[1][4].extend([u"\u00A3", u"$", u"\u20AC"]) return keyList def swiss(self, base): keyList = copy.deepcopy(base) keyList[0][0][0] = u"\u00A7" keyList[0][0][11] = u"'" keyList[0][0][12] = u"^" keyList[0][2][12] = u"$" keyList[0][3][12] = u"\u20AC" keyList[0][4][7] = u"\u00E0" keyList[0][4][8] = u"\u00E8" keyList[0][4][9] = u"\u00E9" keyList[0][4].extend([u"@", u"!", u"\u00AC", u"\\"]) keyList[1][0][1] = u"+" keyList[1][0][3] = u"*" keyList[1][0][4] = u"\u00E7" keyList[1][0][11] = u"?" keyList[1][0][12] = u"`" keyList[1][2][12] = u"\u00A3" keyList[1][3][12] = u"\u00A2" keyList[1][4][9] = u"\u00AC" keyList[1][4][9] = u"\u00A6" keyList[1][4][7] = u"\u00C0" keyList[1][4][8] = u"\u00C8" keyList[1][4][9] = u"\u00C9" keyList[1][4].extend([u"#", u"|", u"\u00A6"]) return keyList def ukranian(self, base): keyList = copy.deepcopy(base) keyList[0][1][12] = u"\u0457" keyList[0][2][2] = u"\u0456" keyList[0][2][11] = u"\u0454" keyList[0][3][11] = u"\u0491" keyList[0][4].append(u"@") keyList[1][1][12] = u"\u0407" keyList[1][2][2] = u"\u0406" keyList[1][2][11] = u"\u0404" keyList[1][3][11] = u"\u0490" keyList[1][4].append(u"#") return keyList def unitedKingdom(self, base): keyList = copy.deepcopy(base) keyList[0][1][13] = u"\u00A6" keyList[0][2][12] = u"#" keyList[0][3] = [u"SHIFT", u"\\", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", u".", u"/", u"", u"SHIFT"] # keyList[0][-1].extend([u"\u00E1", u"\u00E9", u"\u00ED", u"\u00F3", u"\u00FA"]) # English users don't use the accented characters. keyList[1][0][0] = u"\u00AC" keyList[1][0][2] = u"\"" keyList[1][0][3] = u"\u00A3" keyList[1][1][13] = u"\u20AC" keyList[1][2][11] = u"@" keyList[1][2][12] = u"~" keyList[1][3] = [u"SHIFT", u"|", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u"<", u">", u"?", u"", u"SHIFT"] # keyList[1][-1].extend([u"\u00C1", u"\u00C9", u"\u00CD", u"\u00D3", u"\u00DA"]) # English users don't use the accented characters. return keyList def smsGotChar(self): if self.smsChar and self.selectAsciiKey(self.smsChar): self.processSelect() def setLocale(self): self.language, self.location, self.keyList = self.locales.get(self.lang, [None, None, None]) if self.language is None or self.location is None or self.keyList is None: self.lang = "en_EN" self.language = _("English") self.location = _("Various") self.keyList = self.english_EN_US self.shiftLevel = 0 self["locale"].setText(_("Locale") + ": " + self.lang + " (" + self.language + " - " + self.location + ")") def buildVirtualKeyBoard(self): self.shiftLevels = len(self.keyList) if self.shiftLevel >= self.shiftLevels: self.shiftLevel = 0 self.keyboardWidth = len(self.keyList[self.shiftLevel][0]) self.keyboardHeight = len(self.keyList[self.shiftLevel]) self.maxKey = self.keyboardWidth * (self.keyboardHeight - 1) + len(self.keyList[self.shiftLevel][-1]) - 1 # print "[VirtualKeyBoard] DEBUG: Width=%d, Height=%d, Keys=%d, maxKey=%d, shiftLevels=%d" % (self.keyboardWidth, self.keyboardHeight, self.maxKey + 1, self.maxKey, self.shiftLevels) self.list = [] for keys in self.keyList[self.shiftLevel]: self.list.append(self.virtualKeyBoardEntryComponent(keys)) self.previousSelectedKey = [] if self.selectedKey is None: self.selectedKey = self.keyboardWidth self.markSelectedKey() def virtualKeyBoardEntryComponent(self, keys): res = [keys] text = [] offset = 14 - self.keyboardWidth # 14 represents the maximum buttons per row as defined here and in the skin (14 x self.width). x = self.width * offset / 2 if offset % 2: x += self.width / 2 for key in keys: image = self.keyImages[self.shiftLevel].get(key, None) if image: width = image.size().width() res.append(MultiContentEntryPixmapAlphaBlend(pos=(x, 0), size=(width, self.height), png=image)) else: width = self.width res.append(MultiContentEntryPixmapAlphaBlend(pos=(x, 0), size=(width, self.height), png=self.keyBackgrounds.get(key.split("__")[0], self.key_bg))) if "__" in key: key = key.split("__")[1] if not "__HIDE" in key else u"" if len(key) > 1: # NOTE: UTF8 / Unicode glyphs only count as one character here. text.append(MultiContentEntryText(pos=(x, 0), size=(width, self.height), font=1, flags=RT_HALIGN_CENTER | RT_VALIGN_CENTER, text=_(key.encode("utf-8")), color=self.shiftColors[self.shiftLevel])) else: text.append(MultiContentEntryText(pos=(x, 0), size=(width, self.height), font=0, flags=RT_HALIGN_CENTER | RT_VALIGN_CENTER, text=key.encode("utf-8"), color=self.shiftColors[self.shiftLevel])) x += width return res + text def markSelectedKey(self): for key in self.previousSelectedKey: self.list[key] = self.list[key][:-1] self.previousSelectedKey = [] if self.selectedKey > self.maxKey: self.selectedKey = self.maxKey selectedKeyboardKey = self.selectedKey / self.keyboardWidth selectedKeyModulus = self.selectedKey % self.keyboardWidth if "__" not in self.keyList[self.shiftLevel][selectedKeyboardKey][selectedKeyModulus]: x = self.list[selectedKeyboardKey][selectedKeyModulus + 1][1] self.list[selectedKeyboardKey].append(MultiContentEntryPixmapAlphaBlend(pos=(x, 0), size=(self.key_sel_width, self.height), png=self.key_sel)) self.previousSelectedKey.append(selectedKeyboardKey) else: selectedKeyShift = self.selectedKey while True: selectedKeyboardKey = selectedKeyShift / self.keyboardWidth selectedKeyModulus = selectedKeyShift % self.keyboardWidth selectedBg = self.keyList[self.shiftLevel][selectedKeyboardKey][selectedKeyModulus].split("__")[0] x = self.list[selectedKeyboardKey][selectedKeyModulus + 1][1] if selectedBg == "LongL": self.list[selectedKeyboardKey].append(MultiContentEntryPixmapAlphaBlend(pos=(x, 0), size=(self.key_sel_width, self.height), png=self.key_longl_sel)) self.previousSelectedKey.append(selectedKeyboardKey) break elif selectedBg == "LongM": self.list[selectedKeyboardKey].append(MultiContentEntryPixmapAlphaBlend(pos=(x, 0), size=(self.key_sel_width, self.height), png=self.key_longm_sel)) self.previousSelectedKey.append(selectedKeyboardKey) selectedKeyShift -= 1 if selectedKeyShift < 0: break selectedKeyShift = self.selectedKey while True: selectedKeyboardKey = selectedKeyShift / self.keyboardWidth selectedKeyModulus = selectedKeyShift % self.keyboardWidth selectedBg = self.keyList[self.shiftLevel][selectedKeyboardKey][selectedKeyModulus].split("__")[0] x = self.list[selectedKeyboardKey][selectedKeyModulus + 1][1] if selectedBg == "LongR": self.list[selectedKeyboardKey].append(MultiContentEntryPixmapAlphaBlend(pos=(x, 0), size=(self.key_sel_width, self.height), png=self.key_longr_sel)) self.previousSelectedKey.append(selectedKeyboardKey) break elif selectedBg == "LongM" and selectedKeyShift > self.selectedKey: self.list[selectedKeyboardKey].append(MultiContentEntryPixmapAlphaBlend(pos=(x, 0), size=(self.key_sel_width, self.height), png=self.key_longm_sel)) self.previousSelectedKey.append(selectedKeyboardKey) selectedKeyShift += 1 if selectedKeyShift > self.maxKey: break self["list"].setList(self.list) def processSelect(self): self.smsChar = None text = self.keyList[self.shiftLevel][self.selectedKey / self.keyboardWidth][self.selectedKey % self.keyboardWidth].encode("UTF-8") upperText = text.upper() if "__" in upperText: upperText = upperText.split("__")[1] if text == u"": pass elif upperText == u"ALL": self["text"].markAll() elif upperText == u"BACK": self["text"].deleteBackward() elif upperText == u"BACKSPACE": self["text"].deleteBackward() elif upperText == u"BLANK": pass elif upperText == u"CLR": self["text"].deleteAllChars() self["text"].update() elif upperText == u"DEL": self["text"].deleteForward() elif upperText == u"ENTER": self.enter() elif upperText == u"ESC": self.cancel() elif upperText == u"EXIT": self.cancel() elif upperText == u"FIRST": self["text"].home() elif upperText == u"LOC": self.localeMenu() elif upperText == u"LAST": self["text"].end() elif upperText == u"LEFT": self["text"].left() elif upperText == u"OK": self.enter() elif upperText == u"RIGHT": self["text"].right() elif upperText == u"ENTER": self.enter() elif upperText == u"SHIFT": self.shiftClicked() elif upperText == u"Shift": self.shiftClicked() elif upperText == u"SPACE": self["text"].char(" ".encode("UTF-8")) else: self["text"].char(text.encode("UTF-8")) def cancel(self): self.close(None) def save(self): # Deprecated legacy interface to new enter self.enter() def enter(self): self.close(self["text"].getText()) def localeMenu(self): languages = [] for locale, data in self.locales.iteritems(): languages.append((data[0] + " - " + data[1] + " (" + locale + ")", locale)) languages = sorted(languages) index = 0 default = 0 for item in languages: if item[1] == self.lang: default = index break index += 1 self.session.openWithCallback(self.localeMenuCallback, ChoiceBox, _("Available locales are:"), list=languages, selection=default, keys=[]) def localeMenuCallback(self, choice): if choice: self.lang = choice[1] self.setLocale() self.buildVirtualKeyBoard() def shiftClicked(self): self.smsChar = None self.shiftLevel = (self.shiftLevel + 1) % self.shiftLevels nextLevel = (self.shiftLevel + 1) % self.shiftLevels self["key_blue"].setText(self.shiftMsgs[nextLevel]) self.buildVirtualKeyBoard() def keyToggleOW(self): self["text"].toggleOverwrite() self.overwrite = not self.overwrite if self.overwrite: self["mode"].setText(_("OVR")) else: self["mode"].setText(_("INS")) def backClicked(self): self["text"].deleteBackward() def forwardClicked(self): self["text"].deleteForward() def cursorFirst(self): self["text"].home() def cursorLeft(self): self["text"].left() def cursorRight(self): self["text"].right() def cursorLast(self): self["text"].end() def up(self): self.smsChar = None self.selectedKey -= self.keyboardWidth if self.selectedKey < 0: self.selectedKey = self.maxKey / self.keyboardWidth * self.keyboardWidth + self.selectedKey % self.keyboardWidth if self.selectedKey > self.maxKey: self.selectedKey -= self.keyboardWidth self.markSelectedKey() def left(self): self.smsChar = None selectedKeyboardKey = self.selectedKey / self.keyboardWidth self.selectedKey = selectedKeyboardKey * self.keyboardWidth + (self.selectedKey + self.keyboardWidth - 1) % self.keyboardWidth if self.selectedKey > self.maxKey: self.selectedKey = self.maxKey selectedBg = self.keyList[self.shiftLevel][selectedKeyboardKey][self.selectedKey % self.keyboardWidth].split("__")[0] if self.selectedKey < self.maxKey and selectedBg == "LongM" or selectedBg == "LongL": self.left() else: self.markSelectedKey() def right(self): self.smsChar = None selectedKeyboardKey = self.selectedKey / self.keyboardWidth self.selectedKey = selectedKeyboardKey * self.keyboardWidth + (self.selectedKey + 1) % self.keyboardWidth if self.selectedKey > self.maxKey: self.selectedKey = selectedKeyboardKey * self.keyboardWidth selectedBg = self.keyList[self.shiftLevel][selectedKeyboardKey][self.selectedKey % self.keyboardWidth].split("__")[0] if self.selectedKey > 0 and selectedBg == "LongM" or selectedBg == "LongR": self.right() else: self.markSelectedKey() def down(self): self.smsChar = None self.selectedKey += self.keyboardWidth if self.selectedKey > self.maxKey: self.selectedKey %= self.keyboardWidth self.markSelectedKey() def keyNumberGlobal(self, number): self.smsChar = self.sms.getKey(number) self.selectAsciiKey(self.smsChar) def keyGotAscii(self): self.smsChar = None if self.selectAsciiKey(str(unichr(getPrevAsciiCode()).encode("utf-8"))): self.processSelect() def selectAsciiKey(self, char): if char == u" ": char = u"SPACE" self.shiftLevel = -1 for keyList in (self.keyList): self.shiftLevel = (self.shiftLevel + 1) % self.shiftLevels self.buildVirtualKeyBoard() selkey = 0 for keys in keyList: for key in keys: if key == char: self.selectedKey = selkey self.markSelectedKey() return True selkey += 1 return False
class ServiceList(HTMLComponent, GUIComponent): MODE_NORMAL = 0 MODE_FAVOURITES = 1 KEY_BEGIN_MARGIN = "beginMargin" KEY_END_MARGIN = "endMargin" KEY_PICON_WIDTH = "piconWidth" KEY_PICON_WIDTH_BIG = "piconWidthBig" KEY_PICON_OFFSET = "piconOffset" KEY_PROGRESS_BAR_WIDTH = "progressBarWidth" KEY_PROGRESS_BAR_MARGIN = "progressBarMargin" KEY_PROGRESS_BAR_HEIGHT = "progressBarHeight" KEY_SERVICE_INFO_HEIGHT_ADD = "serviceInfoHeightAdd" KEY_SERVICE_ITEM_HEIGHT = "serviceItemHeight" KEY_SERVICE_ITEM_HEIGHT_LARGE = "serviceItemHeightLarge" KEY_SERVICE_NUMBER_WIDTH = "serviceNumberWidth" KEY_TEXT_OFFSET = "textOffset" def getDesktopWith(self): return getDesktop(0).size().width() def __init__(self, session=None): GUIComponent.__init__(self) self._componentSizes = componentSizes[componentSizes.SERVICE_LIST] Log.i(self._componentSizes) tlf = TemplatedListFonts() upper_service_name_limit = self.getDesktopWith() / 3 config.usage.configselection_servicenamecolwidth.limits = [ (100, upper_service_name_limit), ] self.session = session self.mode = self.MODE_NORMAL self.picFolder = LoadPixmap(cached=True, path=resolveFilename( SCOPE_CURRENT_SKIN, "skin_default/icons/folder.png")) self.picMarker = LoadPixmap( resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/marker.png")) self.picDVB_S = LoadPixmap( resolveFilename(SCOPE_CURRENT_SKIN, "ico_dvb_s-fs8.png")) self.picDVB_C = LoadPixmap( resolveFilename(SCOPE_CURRENT_SKIN, "ico_dvb_c-fs8.png")) self.picDVB_T = LoadPixmap( resolveFilename(SCOPE_CURRENT_SKIN, "ico_dvb_t-fs8.png")) self.picServiceGroup = LoadPixmap( resolveFilename(SCOPE_CURRENT_SKIN, "ico_service_group-fs8.png")) self.markedForeground = 0xffffff self.markedBackground = 0xff0000 self.markedForegroundSelected = 0xffffff self.markedBackgroundSelected = 0x800000 colors = TemplatedColors().colors if "ListboxMarkedForeground" in colors: self.markedForeground = colors["ListboxMarkedForeground"] if "ListboxMarkedBackground" in colors: self.markedBackground = colors["ListboxMarkedBackground"] if "ListboxMarkedAndSelectedForeground" in colors: self.markedForegroundSelected = colors[ "ListboxMarkedAndSelectedForeground"] if "ListboxMarkedAndSelectedBackground" in colors: self.markedBackgroundSelected = colors[ "ListboxMarkedAndSelectedBackground"] self.serviceNotAvail = 0xbbbbbb self.serviceEventProgressbarColor = None self.serviceEventProgressbarColorSelected = None self.serviceEventProgressbarBackColor = None self.serviceEventProgressbarBackColorSelected = None self.serviceEventProgressbarBorderColor = None self.serviceEventProgressbarBorderColorSelected = None self.serviceDescriptionColor = 0xe7b53f self.serviceDescriptionColorSelected = 0xe7b53f self.recordingColor = 0xff4A3C self.recordingColorSelected = 0xff4A3C self.additionalInfoColor = None self.additionalInfoColorSelected = None self.picServiceEventProgressbar = None self.selectionPixmapStandard = None self.selectionPixmapBig = None self.l = eListboxServiceContent() self.l.setBuildFunc(self.buildOptionEntry, True) self.l.setFont( 0, gFont(tlf.face(TemplatedListFonts.SMALL), tlf.size(TemplatedListFonts.SMALL))) # AdditionalInfoFont self.l.setFont( 1, gFont(tlf.face(TemplatedListFonts.MEDIUM), tlf.size(TemplatedListFonts.MEDIUM))) # ServiceNumberFont self.l.setFont(2, gFont(tlf.face(TemplatedListFonts.BIG), tlf.size( TemplatedListFonts.BIG))) # ServiceNameFont self.l.setFont(3, gFont(tlf.face(TemplatedListFonts.SMALL), tlf.size( TemplatedListFonts.SMALL))) # ServiceInfoFont self.serviceNameFont = gFont(tlf.face(TemplatedListFonts.BIG), tlf.size(TemplatedListFonts.BIG)) self.serviceInfoFontHeight = tlf.size(TemplatedListFonts.SMALL) self.serviceInfoHeight = self.serviceInfoFontHeight + self._componentSizes.get( self.KEY_SERVICE_INFO_HEIGHT_ADD, 6) self.additionalInfoFont = gFont(tlf.face(TemplatedListFonts.SMALL), tlf.size(TemplatedListFonts.SMALL)) self.list = [] self.size = 0 self.service_center = eServiceCenter.getInstance() self.numberoffset = 0 self.is_playable_ignore = eServiceReference() self.root = None self.itemHeight = self._componentSizes.get( self.KEY_SERVICE_ITEM_HEIGHT, 28) self.itemHeightHigh = self._componentSizes.get( self.KEY_SERVICE_ITEM_HEIGHT_LARGE, 60) self.l.setItemHeight(self.itemHeight) self.onSelectionChanged = [] self.recordingList = {} self.piconLoader = PiconLoader() if self.session: self.session.nav.RecordTimer.on_state_change.append( self.onTimerEntryStateChange) config.usage.configselection_showrecordings.addNotifier( self.getRecordingList, initial_call=True) config.usage.configselection_bigpicons.addNotifier(self.setItemHeight, initial_call=True) config.usage.configselection_secondlineinfo.addNotifier( self.setItemHeight, initial_call=False) self._reloadTimer = eTimer() self.__reloadTimerConn = self._reloadTimer.timeout.connect( self._reload) def onShow(self): GUIComponent.onShow(self) self._resetTimer() def onHide(self): GUIComponent.onHide(self) self._reloadTimer.stop() def _reload(self): self.l.refresh() self._resetTimer() def _resetTimer(self): secs = 60 - datetime.now().second #next full minute self._reloadTimer.startLongTimer(secs) def getRecordingList(self, configElement=None): self.recordingList = {} if config.usage.configselection_showrecordings.value: if NavigationInstance.instance.getRecordings(): for timer in NavigationInstance.instance.RecordTimer.timer_list: if timer.state == TimerEntry.StateRunning and not timer.justplay and hasattr( timer, "Filename"): self.recordingList[str(timer.service_ref)] = 1 def onTimerEntryStateChange(self, timer): if config.usage.configselection_showrecordings.value: if hasattr( timer, "Filename" ) and not timer.justplay and timer.state == TimerEntry.StateRunning: self.recordingList[str(timer.service_ref)] = 1 else: if self.recordingList.has_key(str(timer.service_ref)): del self.recordingList[str(timer.service_ref)] def setItemHeight(self, configElement=None): if (config.usage.configselection_bigpicons.value or config.usage.configselection_secondlineinfo.value != "0" ) and self.mode == self.MODE_FAVOURITES: self.l.setItemHeight(self.itemHeightHigh) if self.instance is not None and self.selectionPixmapBig: self.instance.setSelectionPicture(self.selectionPixmapBig) else: self.l.setItemHeight(self.itemHeight) if self.instance is not None and self.selectionPixmapStandard: self.instance.setSelectionPicture(self.selectionPixmapStandard) def _buildOptionEntryProgressBar(self, event, xoffset, width, height): percent = 0 progressW = self._progressBarWidth() progressH = self._componentSizes.get(self.KEY_PROGRESS_BAR_HEIGHT, 8) if event and event.getDuration(): now = int(time()) percent = 100 * (now - event.getBeginTime()) / event.getDuration() top = int((height - progressH) / 2) if self.picServiceEventProgressbar is None: return (eListboxPythonMultiContent.TYPE_PROGRESS, xoffset, top, progressW, progressH, percent, 1, self.serviceEventProgressbarColor, self.serviceEventProgressbarColorSelected, self.serviceEventProgressbarBackColor, self.serviceEventProgressbarBackColorSelected) else: return (eListboxPythonMultiContent.TYPE_PROGRESS_PIXMAP, xoffset, top, progressW, progressH, percent, self.picServiceEventProgressbar, 1, self.serviceEventProgressbarBorderColor, self.serviceEventProgressbarBorderColorSelected, self.serviceEventProgressbarBackColor, self.serviceEventProgressbarBackColorSelected) def _progressBarWidth(self, withOffset=False, withProgressBarSize=True): width = 0 if withProgressBarSize: width += self._componentSizes.get(self.KEY_PROGRESS_BAR_WIDTH, 52) if withOffset: width += self._componentSizes.get(self.KEY_PROGRESS_BAR_MARGIN, 8) return width def _calcTextWidth(self, text, font=None, size=None): if size: self.textRenderer.resize(size) if font: self.textRenderer.setFont(font) self.textRenderer.setText(text) return self.textRenderer.calculateSize().width() def _buildOptionEntryServicePixmap(self, service): pixmap = None if service.flags & eServiceReference.isMarker: pixmap = self.picMarker elif service.flags & eServiceReference.isGroup: pixmap = self.picServiceGroup elif service.flags & eServiceReference.isDirectory: pixmap = self.picFolder else: orbpos = service.getUnsignedData(4) >> 16 if orbpos == 0xFFFF: pixmap = self.picDVB_C elif orbpos == 0xEEEE: pixmap = self.picDVB_T else: pixmap = self.picDVB_S return pixmap def _buildOptionEntryAddTimeDisplay(self, event, isPlayable, columnStyle): addtimedisplay = "" addtimedisplayWidth = 0 if not (config.usage.configselection_showadditionaltimedisplay.value != "0" and event and isPlayable): return addtimedisplay, addtimedisplayWidth textTpl = "" maxTimeValue = 9999 if config.usage.configselection_showadditionaltimedisplay.value == "1": # percent now = int(time()) percent = 100 * (now - event.getBeginTime()) / event.getDuration() addtimedisplay = "%d%%" % percent textTpl = "100%" elif config.usage.configselection_showadditionaltimedisplay.value == "2": # remain now = int(time()) remain = int( (event.getBeginTime() + event.getDuration() - now) / 60) addtimedisplay = "+%d min" % (remain, ) textTpl = "+%d min" % (maxTimeValue, ) elif config.usage.configselection_showadditionaltimedisplay.value == "3": # Remain / duration now = int(time()) remain = int( (event.getBeginTime() + event.getDuration() - now) / 60) duration = int(event.getDuration() / 60) addtimedisplay = "+%d/%d min" % (remain, duration) textTpl = "+%d/%d min" % (maxTimeValue, maxTimeValue) elif config.usage.configselection_showadditionaltimedisplay.value == "4": # elapsed now = int(time()) elapsed = int((now - event.getBeginTime()) / 60) addtimedisplay = "%d min" % (elapsed, ) textTpl = "%d min" % (maxTimeValue, ) elif config.usage.configselection_showadditionaltimedisplay.value == "5": # elapsed / duration now = int(time()) elapsed = int((now - event.getBeginTime()) / 60) duration = int(event.getDuration() / 60) addtimedisplay = "%d/%d min" % (elapsed, duration) textTpl = "%d/%d min" % (maxTimeValue, maxTimeValue) elif config.usage.configselection_showadditionaltimedisplay.value == "6": # elapsed / remain / duration now = int(time()) elapsed = int((now - event.getBeginTime()) / 60) remain = int( (event.getBeginTime() + event.getDuration() - now) / 60) duration = int(event.getDuration() / 60) addtimedisplay = "%d/+%d/%d min" % (elapsed, remain, duration) textTpl = "%d/+%d/%d mwidthin" % (maxTimeValue, maxTimeValue, maxTimeValue) elif config.usage.configselection_showadditionaltimedisplay.value == "7": # begin - end time beginTime = localtime(event.getBeginTime()) endTime = localtime(event.getBeginTime() + event.getDuration()) addtimedisplay = "%02d:%02d - %02d:%02d" % ( beginTime[3], beginTime[4], endTime[3], endTime[4]) textTpl = "00:00 - 00:000" if columnStyle: addtimedisplayWidth = self._calcTextWidth( textTpl, font=self.additionalInfoFont, size=eSize(self.getDesktopWith() / 3, 0)) return addtimedisplay, addtimedisplayWidth def _buildOptionEntryServicePicon(self, service): if service.flags & eServiceReference.mustDescent: alist = ServiceReference(service).list() first_in_alternative = alist and alist.getNext() if first_in_alternative: service_str = first_in_alternative.toString() else: service_str = service.toString() else: service_str = service.toString() return self.piconLoader.getPicon(service_str) def _checkHasRecording(self, service, isPlayable): if not config.usage.configselection_showrecordings.value: return False if self.recordingList.has_key(service.toString()): return True if isPlayable and len( self.recordingList ) and service.flags & eServiceReference.mustDescent: alist = ServiceReference(service).list() while True: aservice = alist.getNext() if not aservice.valid(): break if self.recordingList.has_key(aservice.toString()): return True return False def buildOptionEntry(self, service, **args): width = self.l.getItemSize().width() width -= self._componentSizes.get(self.KEY_END_MARGIN, 5) height = self.l.getItemSize().height() selected = args["selected"] res = [None] showListNumbers = config.usage.configselection_showlistnumbers.value showPicons = self.mode == self.MODE_FAVOURITES and config.usage.configselection_showpicons.value showServiceName = self.mode == self.MODE_NORMAL or ( self.mode == self.MODE_FAVOURITES and config.usage.configselection_showservicename.value) showProgressbar = config.usage.show_event_progress_in_servicelist.value progressbarPosition = config.usage.configselection_progressbarposition.value servicenameWidth = config.usage.configselection_servicenamecolwidth.value columnStyle = config.usage.configselection_columnstyle.value additionalposition = config.usage.configselection_additionaltimedisplayposition.value bigPicons = self.mode == self.MODE_FAVOURITES and config.usage.configselection_bigpicons.value secondlineinfo = config.usage.configselection_secondlineinfo.value # get service information service_info = self.service_center.info(service) isMarker = service.flags & eServiceReference.isMarker isPlayable = not (service.flags & eServiceReference.isDirectory or isMarker) recording = self._checkHasRecording(service, isPlayable) marked = 0 if self.l.isCurrentMarked() and selected: marked = 2 elif self.l.isMarked(service): if selected: marked = 2 else: marked = 1 if marked == 1: # marked additionalInfoColor = serviceDescriptionColor = forgroundColor = self.markedForeground backgroundColor = self.markedBackground forgroundColorSel = backgroundColorSel = additionalInfoColorSelected = serviceDescriptionColorSelected = None elif marked == 2: # marked and selected additionalInfoColorSelected = serviceDescriptionColorSelected = forgroundColorSel = self.markedForegroundSelected backgroundColorSel = self.markedBackgroundSelected forgroundColor = additionalInfoColor = serviceDescriptionColor = backgroundColor = None else: if recording: forgroundColor = additionalInfoColor = serviceDescriptionColor = self.recordingColor forgroundColorSel = additionalInfoColorSelected = serviceDescriptionColorSelected = self.recordingColorSelected backgroundColor = backgroundColorSel = None else: forgroundColor = forgroundColorSel = backgroundColor = backgroundColorSel = None serviceDescriptionColor = self.serviceDescriptionColor serviceDescriptionColorSelected = self.serviceDescriptionColorSelected additionalInfoColor = self.additionalInfoColor additionalInfoColorSelected = self.additionalInfoColorSelected if (marked == 0 and isPlayable and service_info and not service_info.isPlayable(service, self.is_playable_ignore)): forgroundColor = forgroundColorSel = additionalInfoColor = additionalInfoColorSelected = serviceDescriptionColor = serviceDescriptionColorSelected = self.serviceNotAvail # set windowstyle if marked > 0: res.append( (eListboxPythonMultiContent.TYPE_TEXT, 0, 0, width, height, 1, RT_HALIGN_RIGHT, "", forgroundColor, forgroundColorSel, backgroundColor, backgroundColorSel)) info = self.service_center.info(service) serviceName = info and info.getName(service) or "<n/a>" event = info and info.getEvent(service) index = self.getCurrentIndex() xoffset = self._componentSizes.get(self.KEY_BEGIN_MARGIN, 5) pixmap = self._buildOptionEntryServicePixmap(service) drawProgressbar = isPlayable and showProgressbar progressBarWidth = self._progressBarWidth(withOffset=True) textOffset = self._componentSizes.get(self.KEY_TEXT_OFFSET, 10) if pixmap is not None: pixmap_size = self.picMarker.size() pix_width = pixmap_size.width() pix_height = pixmap_size.height() ypos = (height - pix_height) / 2 res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, xoffset, ypos, pix_width, pix_height, pixmap)) xoffset += pix_width + self._componentSizes.get( self.KEY_PICON_OFFSET, 8) if self.mode != self.MODE_NORMAL: # servicenumber if not (service.flags & eServiceReference.isMarker) and showListNumbers: markers_before = self.l.getNumMarkersBeforeCurrent() text = "%d" % (self.numberoffset + index + 1 - markers_before) nameWidth = self._componentSizes.get( self.KEY_SERVICE_NUMBER_WIDTH, 50) res.append( (eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, nameWidth, height, 1, RT_HALIGN_RIGHT | RT_VALIGN_CENTER, text, forgroundColor, forgroundColorSel, backgroundColor, backgroundColorSel)) xoffset += nameWidth + textOffset # picons if isPlayable and showPicons: picon = self._buildOptionEntryServicePicon(service) if bigPicons: pix_width = self._componentSizes.get(self.KEY_PICON_WIDTH_BIG, 108) else: pix_width = self._componentSizes.get(self.KEY_PICON_WIDTH, 58) if picon: res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, xoffset, 0, pix_width, height, picon)) xoffset += pix_width xoffset += self._componentSizes.get(self.KEY_PICON_OFFSET, 8) # progressbar between servicenumber and servicename if drawProgressbar and progressbarPosition == "0": res.append( self._buildOptionEntryProgressBar(event, xoffset, width, height)) xoffset += progressBarWidth addtimedisplay, addtimedisplayWidth = self._buildOptionEntryAddTimeDisplay( event, isPlayable, columnStyle) if columnStyle: rwidth = 0 # servicename if (isPlayable and showServiceName) or not isPlayable: if isPlayable: rwidth = servicenameWidth # space for servicename else: rwidth = width - xoffset # space for servicename res.append( (eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, rwidth, height, 2, RT_HALIGN_LEFT | RT_VALIGN_CENTER, serviceName, forgroundColor, forgroundColorSel, backgroundColor, backgroundColorSel)) xoffset += rwidth + textOffset # progressbar between servicename and service description if drawProgressbar and progressbarPosition == "1": res.append( self._buildOptionEntryProgressBar( event, xoffset, width, height)) xoffset += progressBarWidth if event and isPlayable: rwidth = width - xoffset if drawProgressbar and progressbarPosition == "2": rwidth -= self._progressBarWidth(withOffset=True, withProgressBarSize=False) rwidth -= self._progressBarWidth(withOffset=True, withProgressBarSize=True) if addtimedisplay != "": if additionalposition == "0": # add time text before service description res.append( (eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, addtimedisplayWidth, height, 0, RT_HALIGN_RIGHT | RT_VALIGN_CENTER, addtimedisplay, additionalInfoColor, additionalInfoColorSelected, backgroundColor, backgroundColorSel)) addoffset = addtimedisplayWidth + textOffset xoffset += addoffset rwidth -= addoffset elif additionalposition == "1": rwidth -= addtimedisplayWidth + textOffset # service description if secondlineinfo != "0" and self.mode == self.MODE_FAVOURITES: res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, rwidth, self.serviceInfoHeight, 3, RT_HALIGN_LEFT | RT_VALIGN_CENTER, event.getEventName(), serviceDescriptionColor, serviceDescriptionColorSelected, backgroundColor, backgroundColorSel)) if secondlineinfo == "1": # shortdescription text = event.getShortDescription() else: event_next = eEPGCache.getInstance().lookupEventTime( service, -1, 1) if event_next: beginTime = localtime(event_next.getBeginTime()) endTime = localtime(event_next.getBeginTime() + event_next.getDuration()) text = "%02d:%02d - %02d:%02d %s" % ( beginTime[3], beginTime[4], endTime[3], endTime[4], event_next.getEventName()) else: text = "%s: n/a" % _("upcoming event") res.append( (eListboxPythonMultiContent.TYPE_TEXT, xoffset, self.serviceInfoHeight, rwidth, height - self.serviceInfoHeight, 0, RT_HALIGN_LEFT | RT_VALIGN_CENTER, text, additionalInfoColor, additionalInfoColorSelected, backgroundColor, backgroundColorSel)) else: res.append( (eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, rwidth, height, 3, RT_HALIGN_LEFT | RT_VALIGN_CENTER, event.getEventName(), serviceDescriptionColor, serviceDescriptionColorSelected, backgroundColor, backgroundColorSel)) # progressbar after service description xoffset += rwidth if drawProgressbar and progressbarPosition == "2": xoffset += self._progressBarWidth( withOffset=True, withProgressBarSize=False) res.append( self._buildOptionEntryProgressBar( event, xoffset, width, height)) xoffset += progressBarWidth # add time text at last position if addtimedisplay != "" and additionalposition == "1": xoffset += textOffset res.append( (eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, addtimedisplayWidth, height, 0, RT_HALIGN_RIGHT | RT_VALIGN_CENTER, addtimedisplay, additionalInfoColor, additionalInfoColorSelected, backgroundColor, backgroundColorSel)) else: if event and isPlayable: maxLength = width - xoffset if drawProgressbar and progressbarPosition == "2": # progressbar after service description maxLength -= progressBarWidth length = self._calcTextWidth(serviceName, font=self.serviceNameFont, size=eSize(maxLength, 0)) + textOffset res.append( (eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, length, height, 2, RT_HALIGN_LEFT | RT_VALIGN_CENTER, serviceName, forgroundColor, forgroundColorSel, backgroundColor, backgroundColorSel)) xoffset += length if addtimedisplay != "": if additionalposition == "1": # add time text after service description text = "(%s %s)" % (event.getEventName(), addtimedisplay) else: # add time text before service description text = "(%s %s)" % (addtimedisplay, event.getEventName()) else: text = "(%s)" % (event.getEventName()) length = width - xoffset if drawProgressbar and progressbarPosition == "2": # progressbar after service description length -= progressBarWidth # service description res.append( (eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, length, height, 3, RT_HALIGN_LEFT | RT_VALIGN_CENTER, text, serviceDescriptionColor, serviceDescriptionColorSelected, backgroundColor, backgroundColorSel)) if drawProgressbar and progressbarPosition == "2": xoffset += length + textOffset / 2 res.append( self._buildOptionEntryProgressBar( event, xoffset, width, height)) else: res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, width - xoffset, height, 2, RT_HALIGN_LEFT | RT_VALIGN_CENTER, serviceName, forgroundColor, forgroundColorSel, backgroundColor, backgroundColorSel)) return res def applySkin(self, desktop, parent): attribs = [] for (attrib, value) in self.skinAttributes: if attrib == "foregroundColorMarked": self.markedForeground = parseColor(value) elif attrib == "foregroundColorMarkedSelected": self.markedForegroundSelected = parseColor(value) elif attrib == "backgroundColorMarked": self.markedBackground = parseColor(value) elif attrib == "backgroundColorMarkedSelected": self.markedBackgroundSelected = parseColor(value) elif attrib == "foregroundColorServiceNotAvail": self.serviceNotAvail = parseColor(value) elif attrib == "colorEventProgressbar": self.serviceEventProgressbarColor = parseColor(value) elif attrib == "colorEventProgressbarSelected": self.serviceEventProgressbarColorSelected = parseColor(value) elif attrib == "forgroundColorEventProgressbarBorder": self.serviceEventProgressbarBackColor = parseColor(value) elif attrib == "backgroundColorEventProgressbarBorderSelected": self.serviceEventProgressbarBackColorSelected = parseColor( value) elif attrib == "colorEventProgressbarBorder": self.serviceEventProgressbarBorderColor = parseColor(value) elif attrib == "colorEventProgressbarBorderSelected": self.serviceEventProgressbarBorderColorSelected = parseColor( value) elif attrib == "colorServiceDescription": self.serviceDescriptionColor = parseColor(value) elif attrib == "colorServiceDescriptionSelected": self.serviceDescriptionColorSelected = parseColor(value) elif attrib == "colorRecording": self.recordingColor = parseColor(value) elif attrib == "colorRecordingSelected": self.recordingColorSelected = parseColor(value) elif attrib == "colorAdditionalInfo": self.additionalInfoColor = parseColor(value) elif attrib == "colorAdditionalInfoSelected": self.additionalInfoColorSelected = parseColor(value) elif attrib == "picServiceEventProgressbar": pic = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, value)) if pic: self.picServiceEventProgressbar = pic elif attrib == "serviceItemHeight": self.itemHeight = int(value) elif attrib == "serviceItemHeightHigh": self.itemHeightHigh = int(value) elif attrib == "serviceNameFont": self.l.setFont(2, parseFont(value, ((1, 1), (1, 1)))) self.serviceNameFont = parseFont(value, ((1, 1), (1, 1))) elif attrib == "serviceInfoFont": self.l.setFont(3, parseFont(value, ((1, 1), (1, 1)))) name, size = value.split(';') self.serviceInfoFontHeight = int(size) elif attrib == "serviceNumberFont": self.l.setFont(1, parseFont(value, ((1, 1), (1, 1)))) elif attrib == "additionalInfoFont": self.l.setFont(0, parseFont(value, ((1, 1), (1, 1)))) self.additionalInfoFont = parseFont(value, ((1, 1), (1, 1))) elif attrib == "selectionPixmap": pic = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, value)) if pic: self.selectionPixmapStandard = pic if not config.usage.configselection_bigpicons.value: self.instance.setSelectionPicture( self.selectionPixmapStandard) elif attrib == "selectionPixmapHigh": pic = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, value)) if pic: self.selectionPixmapBig = pic if config.usage.configselection_bigpicons.value: self.instance.setSelectionPicture( self.selectionPixmapBig) else: attribs.append((attrib, value)) self.skinAttributes = attribs return GUIComponent.applySkin(self, desktop, parent) def connectSelChanged(self, fnc): if not fnc in self.onSelectionChanged: self.onSelectionChanged.append(fnc) def disconnectSelChanged(self, fnc): if fnc in self.onSelectionChanged: self.onSelectionChanged.remove(fnc) def selectionChanged(self): for x in self.onSelectionChanged: x() def setCurrent(self, ref): self.l.setCurrent(ref) def getCurrent(self): r = eServiceReference() self.l.getCurrent(r) return r def atBegin(self): return self.instance.atBegin() def atEnd(self): return self.instance.atEnd() def moveUp(self): self.instance.moveSelection(self.instance.moveUp) def moveDown(self): self.instance.moveSelection(self.instance.moveDown) def moveToChar(self, char): Log.d("Next char: %s" % (char, )) index = self.l.getNextBeginningWithChar(char) indexup = self.l.getNextBeginningWithChar(char.upper()) if indexup != 0: if (index > indexup or index == 0): index = indexup self.instance.moveSelectionTo(index) Log.i("Moving to character %s" % (char, )) def moveToNextMarker(self): idx = self.l.getNextMarkerPos() self.instance.moveSelectionTo(idx) def moveToPrevMarker(self): idx = self.l.getPrevMarkerPos() self.instance.moveSelectionTo(idx) def moveToIndex(self, index): self.instance.moveSelectionTo(index) def getCurrentIndex(self): return self.instance.getCurrentIndex() GUI_WIDGET = eListbox def postWidgetCreate(self, instance): instance.setWrapAround(True) instance.setContent(self.l) self.selectionChanged_conn = instance.selectionChanged.connect( self.selectionChanged) self.setMode(self.mode) self.textRenderer = eLabel(self.instance) self.textRenderer.resize(eSize(self.getDesktopWith() / 3, 0)) self.textRenderer.hide() def preWidgetRemove(self, instance): if self.session: self.session.nav.RecordTimer.on_state_change.remove( self.onTimerEntryStateChange) instance.setContent(None) self.selectionChanged_conn = None config.usage.configselection_showrecordings.removeNotifier( self.getRecordingList) config.usage.configselection_bigpicons.removeNotifier( self.setItemHeight) config.usage.configselection_secondlineinfo.removeNotifier( self.setItemHeight) self.piconLoader.finish() def getRoot(self): return self.root def getRootServices(self): serviceHandler = eServiceCenter.getInstance() list = serviceHandler.list(self.root) dest = [] if list is not None: while 1: s = list.getNext() if s.valid(): dest.append(s.toString()) else: break return dest def setNumberOffset(self, offset): self.numberoffset = offset def setPlayableIgnoreService(self, ref): self.is_playable_ignore = ref def setRoot(self, root, justSet=False): self.root = root self.l.setRoot(root, justSet) if not justSet: self.l.sort() self.selectionChanged() def removeCurrent(self): self.l.removeCurrent() def addService(self, service, beforeCurrent=False): self.l.addService(service, beforeCurrent) def finishFill(self): self.l.FillFinished() self.l.sort() # stuff for multiple marks (edit mode / later multiepg) def clearMarks(self): self.l.initMarked() def isMarked(self, ref): return self.l.isMarked(ref) def addMarked(self, ref): self.l.addMarked(ref) def removeMarked(self, ref): self.l.removeMarked(ref) def getMarked(self): i = self.l i.markedQueryStart() ref = eServiceReference() marked = [] while i.markedQueryNext(ref) == 0: marked.append(ref.toString()) ref = eServiceReference() return marked #just for movemode.. only one marked entry.. def setCurrentMarked(self, state): self.l.setCurrentMarked(state) def setMode(self, mode): self.mode = mode self.setItemHeight()
class MovieList(GUIComponent): SORT_ALPHANUMERIC = 1 SORT_RECORDED = 2 SHUFFLE = 3 SORT_ALPHANUMERIC_REVERSE = 4 SORT_RECORDED_REVERSE = 5 SORT_ALPHANUMERIC_FLAT = 6 SORT_ALPHANUMERIC_FLAT_REVERSE = 7 SORT_GROUPWISE = 8 SORT_ALPHA_DATE_OLDEST_FIRST = 9 SORT_ALPHAREV_DATE_NEWEST_FIRST = 10 HIDE_DESCRIPTION = 1 SHOW_DESCRIPTION = 2 def __init__(self, root, sort_type=None, descr_state=None): GUIComponent.__init__(self) self.list = [] self.descr_state = descr_state or self.HIDE_DESCRIPTION self.sort_type = sort_type or self.SORT_GROUPWISE self.firstFileEntry = 0 self.parentDirectory = 0 self.fontName = "Regular" self.fontSize = 20 self.listHeight = None self.listWidth = None self.pbarShift = 5 self.pbarHeight = 16 self.pbarLargeWidth = 48 self.pbarColour = 0x206333 self.pbarColourSeen = 0xffc71d self.pbarColourRec = 0xff001d self.partIconeShift = 5 self.spaceRight = 2 self.spaceIconeText = 2 self.iconsWidth = 22 self.trashShift = 1 self.dirShift = 1 self.columns = (180,200) self.reloadDelayTimer = None self.l = eListboxPythonMultiContent() self.tags = set() self.root = None self._playInBackground = None self._playInForeground = None self._char = '' if root is not None: self.reload(root) self.l.setBuildFunc(self.buildMovieListEntry) self.onSelectionChanged = [ ] self.iconPart = [] for part in range(5): self.iconPart.append(LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, "icons/part_%d_4.png" % part))) self.iconMovieRec = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, "icons/part_new.png")) self.iconMoviePlay = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, "icons/movie_play.png")) self.iconMoviePlayRec = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, "icons/movie_play_rec.png")) self.iconUnwatched = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, "icons/part_unwatched.png")) self.iconFolder = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, "icons/folder.png")) self.iconTrash = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, "icons/trashcan.png")) self.runningTimers = {} self.updateRecordings() self.updatePlayPosCache() def get_playInBackground(self): return self._playInBackground def set_playInBackground(self, value): if self._playInBackground is not value: index = self.findService(self._playInBackground) if index is not None: self.invalidateItem(index) self.l.invalidateEntry(index) index = self.findService(value) if index is not None: self.invalidateItem(index) self.l.invalidateEntry(index) self._playInBackground = value playInBackground = property(get_playInBackground, set_playInBackground) def get_playInForeground(self): return self._playInForeground def set_playInForeground(self, value): self._playInForeground = value playInForeground = property(get_playInForeground, set_playInForeground) def updatePlayPosCache(self): from Screens.InfoBarGenerics import updateresumePointCache updateresumePointCache() def updateRecordings(self, timer=None): if timer is not None: if timer.justplay: return result = {} for timer in NavigationInstance.instance.RecordTimer.timer_list: if timer.isRunning() and not timer.justplay: result[os.path.split(timer.Filename)[1]+'.ts'] = timer if self.runningTimers == result: return self.runningTimers = result if timer is not None: if self.reloadDelayTimer is not None: self.reloadDelayTimer.stop() self.reloadDelayTimer = eTimer() self.reloadDelayTimer.callback.append(self.reload) self.reloadDelayTimer.start(5000, 1) def connectSelChanged(self, fnc): if not fnc in self.onSelectionChanged: self.onSelectionChanged.append(fnc) def disconnectSelChanged(self, fnc): if fnc in self.onSelectionChanged: self.onSelectionChanged.remove(fnc) def selectionChanged(self): for x in self.onSelectionChanged: x() def setDescriptionState(self, val): self.descr_state = val def setSortType(self, type): self.sort_type = type def applySkin(self, desktop, parent): def warningWrongSkinParameter(string): print "[MovieList] wrong '%s' skin parameters" % string def font(value): font = skin.parseFont(value, ((1,1),(1,1))) self.fontName = font.family self.fontSize = font.pointSize def pbarShift(value): self.pbarShift = int(value) def pbarHeight(value): self.pbarHeight = int(value) def pbarLargeWidth(value): self.pbarLargeWidth = int(value) def pbarColour(value): self.pbarColour = skin.parseColor(value).argb() def pbarColourSeen(value): self.pbarColourSeen = skin.parseColor(value).argb() def pbarColourRec(value): self.pbarColourRec = skin.parseColor(value).argb() def partIconeShift(value): self.partIconeShift = int(value) def spaceIconeText(value): self.spaceIconeText = int(value) def iconsWidth(value): self.iconsWidth = int(value) def trashShift(value): self.trashShift = int(value) def dirShift(value): self.dirShift = int(value) def spaceRight(value): self.spaceRight = int(value) def columns(value): self.columns = map(int, value.split(",")) if len(self.columns) != 2: warningWrongSkinParameter(attrib) for (attrib, value) in self.skinAttributes[:]: try: locals().get(attrib)(value) self.skinAttributes.remove((attrib, value)) except: pass rc = GUIComponent.applySkin(self, desktop, parent) self.listHeight = self.instance.size().height() self.listWidth = self.instance.size().width() self.setFontsize() self.setItemsPerPage() return rc def setItemsPerPage(self): if self.listHeight > 0: itemHeight = self.listHeight / config.movielist.itemsperpage.value else: itemHeight = 25 # some default (270/5) self.itemHeight = itemHeight self.l.setItemHeight(itemHeight) self.instance.resize(eSize(self.listWidth, self.listHeight / itemHeight * itemHeight)) def setFontsize(self): self.l.setFont(0, gFont(self.fontName, self.fontSize + config.movielist.fontsize.value)) self.l.setFont(1, gFont(self.fontName, (self.fontSize - 3) + config.movielist.fontsize.value)) def invalidateItem(self, index): x = self.list[index] self.list[index] = (x[0], x[1], x[2], None) def invalidateCurrentItem(self): self.invalidateItem(self.getCurrentIndex()) def buildMovieListEntry(self, serviceref, info, begin, data): switch = config.usage.show_icons_in_movielist.value width = self.l.getItemSize().width() iconSize = self.iconsWidth space = self.spaceIconeText r = self.spaceRight pathName = serviceref.getPath() res = [ None ] if serviceref.flags & eServiceReference.mustDescent: # Directory # Name is full path name if info is None: # Special case: "parent" txt = ".." else: p = os.path.split(pathName) if not p[1]: # if path ends in '/', p is blank. p = os.path.split(p[0]) txt = p[1] if txt == ".Trash": res.append(MultiContentEntryPixmapAlphaBlend(pos=(0,self.trashShift), size=(iconSize,self.iconTrash.size().height()), png=self.iconTrash)) res.append(MultiContentEntryText(pos=(iconSize+space, 0), size=(width-166, self.itemHeight), font=0, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = _("Deleted items"))) res.append(MultiContentEntryText(pos=(width-145-r, 0), size=(145, self.itemHeight), font=1, flags=RT_HALIGN_RIGHT|RT_VALIGN_CENTER, text=_("Trash can"))) return res res.append(MultiContentEntryPixmapAlphaBlend(pos=(0,self.dirShift), size=(iconSize,iconSize), png=self.iconFolder)) res.append(MultiContentEntryText(pos=(iconSize+space, 0), size=(width-166, self.itemHeight), font=0, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = txt)) res.append(MultiContentEntryText(pos=(width-145-r, 0), size=(145, self.itemHeight), font=1, flags=RT_HALIGN_RIGHT|RT_VALIGN_CENTER, text=_("Directory"))) return res if data == -1 or data is None: data = MovieListData() cur_idx = self.l.getCurrentSelectionIndex() x = self.list[cur_idx] # x = ref,info,begin,... data.len = 0 #dont recalc movielist to speedup loading the list self.list[cur_idx] = (x[0], x[1], x[2], data) #update entry in list... so next time we don't need to recalc data.txt = info.getName(serviceref) if config.movielist.hide_extensions.value: fileName, fileExtension = os.path.splitext(data.txt) if fileExtension in KNOWN_EXTENSIONS: data.txt = fileName data.icon = None data.part = None if os.path.split(pathName)[1] in self.runningTimers: if switch == 'i': if (self.playInBackground or self.playInForeground) and serviceref == (self.playInBackground or self.playInForeground): data.icon = self.iconMoviePlayRec else: data.icon = self.iconMovieRec elif switch in ('p', 's'): data.part = 100 if (self.playInBackground or self.playInForeground) and serviceref == (self.playInBackground or self.playInForeground): data.partcol = self.pbarColourSeen else: data.partcol = self.pbarColourRec elif (self.playInBackground or self.playInForeground) and serviceref == (self.playInBackground or self.playInForeground): data.icon = self.iconMoviePlay else: data.part = moviePlayState(pathName + '.cuts', serviceref, data.len) if switch == 'i': if data.part is not None and data.part > 0: data.icon = self.iconPart[data.part // 25] else: if config.usage.movielist_unseen.value: data.icon = self.iconUnwatched elif switch in ('p', 's'): if data.part is not None and data.part > 0: data.partcol = self.pbarColourSeen else: if config.usage.movielist_unseen.value: data.part = 100 data.partcol = self.pbarColour len = data.len if len > 0: len = "%d:%02d" % (len / 60, len % 60) else: len = "" if data: pos = (0,self.partIconeShift) if switch == 'i' and hasattr(data, 'icon') and data.icon is not None: res.append(MultiContentEntryPixmapAlphaBlend(pos=pos, size=(iconSize,data.icon.size().height()), png=data.icon)) elif switch in ('p', 's'): if switch == 'p': iconSize = self.pbarLargeWidth if hasattr(data, 'part') and data.part > 0: res.append(MultiContentEntryProgress(pos=(0,self.pbarShift), size=(iconSize, self.pbarHeight), percent=data.part, borderWidth=2, foreColor=data.partcol, foreColorSelected=None, backColor=None, backColorSelected=None)) elif hasattr(data, 'icon') and data.icon is not None: res.append(MultiContentEntryPixmapAlphaBlend(pos=(0,self.pbarShift), size=(iconSize, self.pbarHeight), png=data.icon)) begin_string = "" if begin > 0: begin_string = ', '.join(FuzzyTime(begin, inPast = True)) ih = self.itemHeight lenSize = ih * 3 # 25 -> 75 dateSize = ih * 145 / 25 # 25 -> 145 res.append(MultiContentEntryText(pos=(iconSize+space, 0), size=(width-iconSize-space-dateSize-r, ih), font = 0, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = data.txt)) res.append(MultiContentEntryText(pos=(width-dateSize-r, 4), size=(dateSize, ih), font=1, flags=RT_HALIGN_RIGHT|RT_VALIGN_CENTER, text=begin_string)) return res def moveToFirstMovie(self): if self.firstFileEntry < len(self.list): self.instance.moveSelectionTo(self.firstFileEntry) else: # there are no movies, just directories... self.moveToFirst() def moveToParentDirectory(self): if self.parentDirectory < len(self.list): self.instance.moveSelectionTo(self.parentDirectory) else: self.moveToFirst() def moveToLast(self): if self.list: self.instance.moveSelectionTo(len(self.list) - 1) def moveToFirst(self): if self.list: self.instance.moveSelectionTo(0) def moveToIndex(self, index): self.instance.moveSelectionTo(index) def getCurrentIndex(self): return self.instance.getCurrentIndex() def getCurrentEvent(self): l = self.l.getCurrentSelection() return l and l[0] and l[1] and l[1].getEvent(l[0]) def getCurrent(self): l = self.l.getCurrentSelection() return l and l[0] def getItem(self, index): if self.list: if len(self.list) > index: return self.list[index] and self.list[index][0] GUI_WIDGET = eListbox def postWidgetCreate(self, instance): instance.setContent(self.l) instance.selectionChanged.get().append(self.selectionChanged) self.setFontsize() def preWidgetRemove(self, instance): instance.setContent(None) instance.selectionChanged.get().remove(self.selectionChanged) def reload(self, root = None, filter_tags = None): if self.reloadDelayTimer is not None: self.reloadDelayTimer.stop() self.reloadDelayTimer = None if root is not None: self.load(root, filter_tags) else: self.load(self.root, filter_tags) self.l.setList(self.list) def removeService(self, service): index = self.findService(service) if index is not None: del self.list[index] self.l.setList(self.list) def findService(self, service): if service is None: return None for index, l in enumerate(self.list): if l[0] == service: return index return None def __len__(self): return len(self.list) def __getitem__(self, index): return self.list[index] def __iter__(self): return self.list.__iter__() def load(self, root, filter_tags): # this lists our root service, then building a # nice list del self.list[:] serviceHandler = eServiceCenter.getInstance() numberOfDirs = 0 reflist = root and serviceHandler.list(root) if reflist is None: print "listing of movies failed" return realtags = set() tags = {} rootPath = os.path.normpath(root.getPath()) parent = None # Don't navigate above the "root" if len(rootPath) > 1 and (os.path.realpath(rootPath) != config.movielist.root.value): parent = os.path.split(os.path.normpath(rootPath))[0] currentfolder = os.path.normpath(rootPath) + '/' if parent and (parent not in defaultInhibitDirs) and not currentfolder.endswith(config.usage.default_path.value): # enigma wants an extra '/' appended if not parent.endswith('/'): parent += '/' ref = eServiceReference("2:0:1:0:0:0:0:0:0:0:" + parent) ref.flags = eServiceReference.flagDirectory self.list.append((ref, None, 0, -1)) numberOfDirs += 1 while 1: serviceref = reflist.getNext() if not serviceref.valid(): break if config.ParentalControl.servicepinactive.value and config.ParentalControl.storeservicepin.value != "never": from Components.ParentalControl import parentalControl if not parentalControl.sessionPinCached and parentalControl.isProtected(serviceref): continue info = serviceHandler.info(serviceref) if info is None: info = justStubInfo begin = info.getInfo(serviceref, iServiceInformation.sTimeCreate) if serviceref.flags & eServiceReference.mustDescent: dirname = info.getName(serviceref) if not dirname.endswith('.AppleDouble/') and not dirname.endswith('.AppleDesktop/') and not dirname.endswith('.AppleDB/') and not dirname.endswith('Network Trash Folder/') and not dirname.endswith('Temporary Items/'): self.list.append((serviceref, info, begin, -1)) numberOfDirs += 1 continue # convert separe-seperated list of tags into a set this_tags = info.getInfoString(serviceref, iServiceInformation.sTags).split(' ') name = info.getName(serviceref) # OSX put a lot of stupid files ._* everywhere... we need to skip them if name[:2] == "._": continue if this_tags == ['']: # No tags? Auto tag! this_tags = name.replace(',',' ').replace('.',' ').replace('_',' ').replace(':',' ').split() else: realtags.update(this_tags) for tag in this_tags: if len(tag) >= 4: if tags.has_key(tag): tags[tag].append(name) else: tags[tag] = [name] # filter_tags is either None (which means no filter at all), or # a set. In this case, all elements of filter_tags must be present, # otherwise the entry will be dropped. if filter_tags is not None: this_tags_fullname = [" ".join(this_tags)] this_tags_fullname = set(this_tags_fullname) this_tags = set(this_tags) if not this_tags.issuperset(filter_tags) and not this_tags_fullname.issuperset(filter_tags): # print "Skipping", name, "tags=", this_tags, " filter=", filter_tags continue self.list.append((serviceref, info, begin, -1)) self.firstFileEntry = numberOfDirs self.parentDirectory = 0 self.list.sort(key=self.buildGroupwiseSortkey) if self.sort_type == MovieList.SORT_ALPHANUMERIC: self.list = sorted(self.list[:numberOfDirs], key=self.buildAlphaNumericSortKey) + sorted(self.list[numberOfDirs:], key=self.buildAlphaNumericSortKey) elif self.sort_type == MovieList.SORT_ALPHANUMERIC_REVERSE: self.list = sorted(self.list[:numberOfDirs], key=self.buildAlphaNumericSortKey, reverse = True) + sorted(self.list[numberOfDirs:], key=self.buildAlphaNumericSortKey, reverse = True) elif self.sort_type == MovieList.SORT_ALPHANUMERIC_FLAT: self.list.sort(key=self.buildAlphaNumericFlatSortKey) elif self.sort_type == MovieList.SORT_ALPHANUMERIC_FLAT_REVERSE: self.list.sort(key=self.buildAlphaNumericFlatSortKey, reverse = True) elif self.sort_type == MovieList.SORT_RECORDED: self.list = sorted(self.list[:numberOfDirs], key=self.buildBeginTimeSortKey) + sorted(self.list[numberOfDirs:], key=self.buildBeginTimeSortKey) elif self.sort_type == MovieList.SORT_RECORDED_REVERSE: self.list = sorted(self.list[:numberOfDirs], key=self.buildBeginTimeSortKey, reverse = True) + sorted(self.list[numberOfDirs:], key=self.buildBeginTimeSortKey, reverse = True) elif self.sort_type == MovieList.SHUFFLE: dirlist = self.list[:numberOfDirs] shufflelist = self.list[numberOfDirs:] random.shuffle(shufflelist) self.list = dirlist + shufflelist elif self.sort_type == MovieList.SORT_ALPHA_DATE_OLDEST_FIRST: self.list = sorted(self.list[:numberOfDirs], key=self.buildAlphaDateSortKey) + sorted(self.list[numberOfDirs:], key=self.buildAlphaDateSortKey) elif self.sort_type == MovieList.SORT_ALPHAREV_DATE_NEWEST_FIRST: self.list = sorted(self.list[:numberOfDirs], key=self.buildAlphaDateSortKey, reverse = True) + sorted(self.list[numberOfDirs:], key=self.buildAlphaDateSortKey, reverse = True) for x in self.list: if x[1]: tmppath = x[1].getName(x[0])[:-1] if x[1].getName(x[0]).endswith('/') else x[1].getName(x[0]) if tmppath.endswith('.Trash'): self.list.insert(0, self.list.pop(self.list.index(x))) break if self.root and numberOfDirs > 0: rootPath = os.path.normpath(self.root.getPath()) if not rootPath.endswith('/'): rootPath += '/' if rootPath != parent: # with new sort types directories may be in between files, so scan whole # list for parentDirectory index. Usually it is the first one anyway for index, item in enumerate(self.list): if item[0].flags & eServiceReference.mustDescent: itempath = os.path.normpath(item[0].getPath()) if not itempath.endswith('/'): itempath += '/' if itempath == rootPath: self.parentDirectory = index break self.root = root # finally, store a list of all tags which were found. these can be presented # to the user to filter the list # ML: Only use the tags that occur more than once in the list OR that were # really in the tag set of some file. # reverse the dictionary to see which unique movie each tag now references rtags = {} for tag, movies in tags.items(): if (len(movies) > 1) or (tag in realtags): movies = tuple(movies) # a tuple can be hashed, but a list not item = rtags.get(movies, []) if not item: rtags[movies] = item item.append(tag) self.tags = {} for movies, tags in rtags.items(): movie = movies[0] # format the tag lists so that they are in 'original' order tags.sort(key = movie.find) first = movie.find(tags[0]) last = movie.find(tags[-1]) + len(tags[-1]) match = movie start = 0 end = len(movie) # Check if the set has a complete sentence in common, and how far for m in movies[1:]: if m[start:end] != match: if not m.startswith(movie[:last]): start = first if not m.endswith(movie[first:]): end = last match = movie[start:end] if m[start:end] != match: match = '' break if match: self.tags[match] = set(tags) continue else: match = ' '.join(tags) if len(match) > 2: #Omit small words self.tags[match] = set(tags) def buildAlphaNumericSortKey(self, x): # x = ref,info,begin,... ref = x[0] name = x[1] and x[1].getName(ref) if ref.flags & eServiceReference.mustDescent: return 0, name and name.lower() or "", -x[2] return 1, name and name.lower() or "", -x[2] # as for buildAlphaNumericSortKey, but without negating dates def buildAlphaDateSortKey(self, x): # x = ref,info,begin,... ref = x[0] name = x[1] and x[1].getName(ref) if ref.flags & eServiceReference.mustDescent: return 0, name and name.lower() or "", x[2] return 1, name and name.lower() or "", x[2] def buildAlphaNumericFlatSortKey(self, x): # x = ref,info,begin,... ref = x[0] name = x[1] and x[1].getName(ref) if name and ref.flags & eServiceReference.mustDescent: # only use directory basename for sorting p = os.path.split(name) if not p[1]: # if path ends in '/', p is blank. p = os.path.split(p[0]) name = p[1] # print "Sorting for -%s-" % name return 1, name and name.lower() or "", -x[2] def buildBeginTimeSortKey(self, x): ref = x[0] if ref.flags & eServiceReference.mustDescent: return 0, x[1] and -os.stat(ref.getPath()).st_mtime return 1, -x[2] def buildGroupwiseSortkey(self, x): # Sort recordings by date, sort MP3 and stuff by name ref = x[0] if ref.type >= eServiceReference.idUser: return self.buildAlphaNumericSortKey(x) else: return self.buildBeginTimeSortKey(x) def moveTo(self, serviceref): index = self.findService(serviceref) if index is not None: self.instance.moveSelectionTo(index) return True return False def moveDown(self): self.instance.moveSelection(self.instance.moveDown) def moveUp(self): self.instance.moveSelection(self.instance.moveUp) def moveToChar(self, char, lbl=None): self._char = char self._lbl = lbl if lbl: lbl.setText(self._char) lbl.visible = True self.moveToCharTimer = eTimer() self.moveToCharTimer.callback.append(self._moveToChrStr) self.moveToCharTimer.start(1000, True) #time to wait for next key press to decide which letter to use... def moveToString(self, char, lbl=None): self._char = self._char + char.upper() self._lbl = lbl if lbl: lbl.setText(self._char) lbl.visible = True self.moveToCharTimer = eTimer() self.moveToCharTimer.callback.append(self._moveToChrStr) self.moveToCharTimer.start(1000, True) #time to wait for next key press to decide which letter to use... def _moveToChrStr(self): currentIndex = self.instance.getCurrentIndex() found = False if currentIndex < (len(self.list) - 1): itemsBelow = self.list[currentIndex + 1:] #first search the items below the selection for index, item in enumerate(itemsBelow): ref = item[0] itemName = getShortName(item[1].getName(ref).upper(), ref) if len(self._char) == 1 and itemName.startswith(self._char): found = True self.instance.moveSelectionTo(index + currentIndex + 1) break elif len(self._char) > 1 and itemName.find(self._char) >= 0: found = True self.instance.moveSelectionTo(index + currentIndex + 1) break if found == False and currentIndex > 0: itemsAbove = self.list[1:currentIndex] #first item (0) points parent folder - no point to include for index, item in enumerate(itemsAbove): ref = item[0] itemName = getShortName(item[1].getName(ref).upper(), ref) if len(self._char) == 1 and itemName.startswith(self._char): found = True self.instance.moveSelectionTo(index + 1) break elif len(self._char) > 1 and itemName.find(self._char) >= 0: found = True self.instance.moveSelectionTo(index + 1) break self._char = '' if self._lbl: self._lbl.visible = False
class VirtualKeyBoard(Screen): def __init__(self, session, title="", **kwargs): Screen.__init__(self, session) self.setTitle(_("Virtual keyboard")) self.keys_list = [] self.shiftkeys_list = [] self.lang = language.getLanguage() self.nextLang = None self.shiftMode = False self.selectedKey = 0 self.smsChar = None self.sms = NumericalTextInput(self.smsOK) self.key_bg = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_bg.png")) self.key_sel = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_sel.png")) self.key_backspace = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_backspace.png")) self.key_all = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_all.png")) self.key_clr = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_clr.png")) self.key_esc = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_esc.png")) self.key_ok = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_ok.png")) self.key_shift = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_shift.png")) self.key_shift_sel = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_shift_sel.png")) self.key_space = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_space.png")) self.key_left = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_left.png")) self.key_right = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_right.png")) self.keyImages = { "BACKSPACE": self.key_backspace, "ALL": self.key_all, "EXIT": self.key_esc, "OK": self.key_ok, "SHIFT": self.key_shift, "SPACE": self.key_space, "LEFT": self.key_left, "RIGHT": self.key_right } self.keyImagesShift = { "BACKSPACE": self.key_backspace, "CLEAR": self.key_clr, "EXIT": self.key_esc, "OK": self.key_ok, "SHIFT": self.key_shift_sel, "SPACE": self.key_space, "LEFT": self.key_left, "RIGHT": self.key_right } self["key_red"] = StaticText(_("Exit")) self["key_green"] = StaticText(_("OK")) self["key_yellow"] = StaticText("") self["country"] = StaticText("") self["header"] = Label(title) self["text"] = Input(currPos=len(kwargs.get("text", "").decode("utf-8",'ignore')), allMarked=False, **kwargs) self["list"] = VirtualKeyBoardList([]) self["actions"] = NumberActionMap(["OkCancelActions", "WizardActions", "ColorActions", "KeyboardInputActions", "InputBoxActions", "InputAsciiActions"], { "gotAsciiCode": self.keyGotAscii, "ok": self.okClicked, "cancel": self.exit, "left": self.left, "right": self.right, "up": self.up, "down": self.down, "red": self.exit, "green": self.ok, "yellow": self.switchLang, "blue": self.shiftClicked, "deleteBackward": self.backClicked, "deleteForward": self.forwardClicked, "back": self.exit, "pageUp": self.cursorRight, "pageDown": self.cursorLeft, "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, }, -2) self.setLang() self.onExecBegin.append(self.setKeyboardModeAscii) self.onLayoutFinish.append(self.buildVirtualKeyBoard) self.onClose.append(self.__onClose) def __onClose(self): self.sms.timer.stop() def switchLang(self): self.lang = self.nextLang self.setLang() self.buildVirtualKeyBoard() def setLang(self): if self.lang == 'ar_AE': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"ض", u"ص", u"ث", u"ق", u"ف", u"غ", u"ع", u"ه", u"خ", u"ح", u"ج", u"د"], [u"ش", u"س", u"ي", u"ب", u"ل", u"ا", u"ت", u"ن", u"م", u"ك", u"ط", u"#"], [u"ئ", u"ء", u"ؤ", u"ر", u"لا", u"ى", u"ة", u"و", u"ز", "ظ", u"ذ", u"CLEAR"], [u"SHIFT", u"SPACE", u"+", u"-", u"*", u"/", u".", u",", u"@", u"%", u"&", u"OK"]] self.shiftkeys_list = [ [u"EXIT", u"!", u'"', u"§", u"$", u"^", u"<", u">", u"(", u")", u"=", u"BACKSPACE"], [u"َ", u"ً", u"ُ", u"ٌ", u"لإ", u"إ", u"‘", u"÷", u"×", u"؛", u"<", u">"], [u"ِ", u"ٍ", u"]", u"[", u"لأ", u"أ", u"ـ", u"،", u"/", u":", u"~", u"'"], [u"ْ", u"}", u"{", u"لآ", u"آ", u"’", u",", u".", u"؟", u":", u"_", u"CLEAR"], [u"SHIFT", u"SPACE", u"?", u"\\", u"=", u"ّ", u"~", u"OK"]] self.nextLang = 'cs_CZ' elif self.lang == 'cs_CZ': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"ú", u"+"], [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ů", u"@", u"#"], [u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL"], [u"SHIFT", u"SPACE", u"ě", u"š", u"č", u"ř", u"ž", u"ý", u"á", u"í", u"é", u"OK"]] self.shiftkeys_list = [ [u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE"], [u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"ť", u"*"], [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"ň", u"ď", u"'"], [u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR"], [u"SHIFT", u"SPACE", u"?", u"\\", u"Č", u"Ř", u"Š", u"Ž", u"Ú", u"Á", u"É", u"OK"]] self.nextLang = 'de_DE' elif self.lang == 'de_DE': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"ü", u"+"], [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ö", u"ä", u"#"], [u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL"], [u"SHIFT", u"SPACE", u"@", u"ß", u"OK", u"LEFT", u"RIGHT"]] self.shiftkeys_list = [ [u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE"], [u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"Ü", u"*"], [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"Ö", u"Ä", u"'"], [u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR"], [u"SHIFT", u"SPACE", u"?", u"\\", u"OK", u"LEFT", u"RIGHT"]] self.nextLang = 'el_GR' elif self.lang == 'el_GR': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"=", u"ς", u"ε", u"ρ", u"τ", u"υ", u"θ", u"ι", u"ο", u"π", u"[", u"]"], [u"α", u"σ", u"δ", u"φ", u"γ", u"η", u"ξ", u"κ", u"λ", u";", u"'", u"-"], [u"\\", u"ζ", u"χ", u"ψ", u"ω", u"β", u"ν", u"μ", u",", ".", u"/", u"ALL"], [u"SHIFT", u"SPACE", u"ά", u"έ", u"ή", u"ί", u"ό", u"ύ", u"ώ", u"ϊ", u"ϋ", u"OK"]] self.shiftkeys_list = [ [u"EXIT", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"*", u"(", u")", u"BACKSPACE"], [u"+", u"€", u"Ε", u"Ρ", u"Τ", u"Υ", u"Θ", u"Ι", u"Ο", u"Π", u"{", u"}"], [u"Α", u"Σ", u"Δ", u"Φ", u"Γ", u"Η", u"Ξ", u"Κ", u"Λ", u":", u'"', u"_"], [u"|", u"Ζ", u"Χ", u"Ψ", u"Ω", u"Β", u"Ν", u"Μ", u"<", u">", u"?", u"CLEAR"], [u"SHIFT", u"SPACE", u"Ά", u"Έ", u"Ή", u"Ί", u"Ό", u"Ύ", u"Ώ", u"Ϊ", u"Ϋ", u"OK"]] self.nextLang = 'es_ES' elif self.lang == 'es_ES': #still missing keys (u"ùÙ") self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"ú", u"+"], [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ó", u"á", u"#"], [u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL"], [u"SHIFT", u"SPACE", u"@", u"Ł", u"ŕ", u"é", u"č", u"í", u"ě", u"ń", u"ň", u"OK"]] self.shiftkeys_list = [ [u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE"], [u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"Ú", u"*"], [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"Ó", u"Á", u"'"], [u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR"], [u"SHIFT", u"SPACE", u"?", u"\\", u"Ŕ", u"É", u"Č", u"Í", u"Ě", u"Ń", u"Ň", u"OK"]] self.nextLang = 'fa_IR' elif self.lang == 'fa_IR': self.keys_list = [ [u"EXIT", u"\u06F1", u"\u06F2", u"\u06F3", u"\u06F4", u"\u06F5", u"\u06F6", u"\u06F7", u"\u06F8", u"\u06F9", u"\u06F0", u"BACKSPACE"], [u"\u0636", u"\u0635", u"\u062B", u"\u0642", u"\u0641", u"\u063A", u"\u0639", u"\u0647", u"\u062E", u"\u062D", u"-", u"\u062C"], [u"\u0634", u"\u0633", u"\u06CC", u"\u0628", u"\u0644", u"\u0627", u"\u062A", u"\u0646", u"\u0645", u"\u06A9", u"\u06AF", u"\u067E"], [u"<", u"\u0638", u"\u0637", u"\u0632", u"\u0631", u"\u0630", u"\u062F", u"\u0626", u"\u0648", ".", u"/", u"ALL"], [u"SHIFT", u"SPACE", u"OK", u"LEFT", u"RIGHT", u"*"]] self.shiftkeys_list = [ [u"EXIT", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"(", u")", u"=", u"BACKSPACE"], [u"\u0636", u"\u0635", u"\u062B", u"\u0642", u"\u060C", u"\u061B", u"\u0639", u"\u0647", u"\u062E", u"\u062D", u"+", u"\u0686"], [u"\u0634", u"\u0633", u"\u06CC", u"\u0628", u"\u06C0", u"\u0622", u"\u062A", u"\u0646", u"\u0645", u"?", u'"', u"|"], [u">", u"\u0629", u"\u064A", u"\u0698", u"\u0624", u"\u0625", u"\u0623", u"\u0621", u";", u":", u"\u061F", u"CLEAR"], [u"SHIFT", u"SPACE", u"OK", u"LEFT", u"RIGHT", u"~"]] self.nextLang = 'fi_FI' elif self.lang == 'fi_FI': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"é", u"+"], [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ö", u"ä", u"#"], [u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL"], [u"SHIFT", u"SPACE", u"@", u"ß", u"ĺ", u"OK", u"LEFT", u"RIGHT"]] self.shiftkeys_list = [ [u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE"], [u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"É", u"*"], [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"Ö", u"Ä", u"'"], [u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR"], [u"SHIFT", u"SPACE", u"?", u"\\", u"Ĺ", u"OK", u"LEFT", u"RIGHT"]] self.nextLang = 'fr_FR' elif self.lang == 'fr_FR': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"a", u"z", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"é", u"è"], [u"q", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"m", u"ê", u"ë"], [u"<", u"w", u"x", u"c", u"v", u"b", u"n", u",", u";", u":", u"=", u"ALL"], [u"SHIFT", u"SPACE", u"ù", u"â", u"ï", u"ô", u"ç", u"#", u"-", u"OK", u"LEFT", u"RIGHT"]] self.shiftkeys_list = [ [u"EXIT", u"&", u'@', u'"', u"€", u"§", u"!", u"ç", u"(", u")", u"_", u"BACKSPACE"], [u"A", u"Z", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"É", u"È"], [u"Q", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"M", u"Ê", u"Ë"], [u">", u"W", u"X", u"C", u"V", u"B", u"N", u"?", u".", u"+", u"~", u"CLEAR"], [u"SHIFT", u"SPACE", u"Ù", u"Â", u"Ï", u"Ô", u"°", u"/",u"\\", u"OK", u"LEFT", u"RIGHT"]] self.nextLang = 'lv_LV' elif self.lang == 'lv_LV': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"q", u"w", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"-", u"š"], [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u";", u"'", u"ū"], [u"<", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", u".", u"ž", u"ALL"], [u"SHIFT", u"SPACE", u"ā", u"č", u"ē", u"ģ", u"ī", u"ķ", u"ļ", u"ņ", u"LEFT", u"RIGHT"]] self.shiftkeys_list = [ [u"EXIT", u"!", u"@", u"$", u"*", u"(", u")", u"_", u"=", u"/", u"\\", u"BACKSPACE"], [u"Q", u"W", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"+", u"Š"], [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u":", u'"', u"Ū"], [u">", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u"#", u"?", u"Ž", u"CLEAR"], [u"SHIFT", u"SPACE", u"Ā", u"Č", u"Ē", u"Ģ", u"Ī", u"Ķ", u"Ļ", u"Ņ", u"LEFT", u"RIGHT"]] self.nextLang = 'pl_PL' elif self.lang == 'pl_PL': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"q", u"w", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"-", u"["], [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u";", u"'", u"\\"], [u"<", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"/", u"ALL"], [u"SHIFT", u"SPACE", u"ą", u"ć", u"ę", u"ł", u"ń", u"ó", u"ś", u"ź", u"ż", u"OK"]] self.shiftkeys_list = [ [u"EXIT", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"(", u")", u"=", u"BACKSPACE"], [u"Q", u"W", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"*", u"]"], [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"?", u'"', u"|"], [u">", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR"], [u"SHIFT", u"SPACE", u"Ą", u"Ć", u"Ę", u"Ł", u"Ń", u"Ó", u"Ś", u"Ź", u"Ż", u"OK"]] self.nextLang = 'ru_RU' elif self.lang == 'ru_RU': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"а", u"б", u"в", u"г", u"д", u"е", u"ё", u"ж", u"з", u"и", u"й", u"+"], [u"к", u"л", u"м", u"н", u"о", u"п", u"р", u"с", u"т", u"у", u"ф", u"#"], [u"<", u"х", u"ц", u"ч", u"ш", u"щ", u"ъ", u"ы", u",", u".", u"-", u"ALL"], [u"SHIFT", u"SPACE", u"@", u"ь", u"э", u"ю", u"я", u"OK", u"LEFT", u"RIGHT"]] self.shiftkeys_list = [ [u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE"], [u"А", u"Б", u"В", u"Г", u"Д", u"Е", u"Ё", u"Ж", u"З", u"И", u"Й", u"*"], [u"К", u"Л", u"М", u"Н", u"О", u"П", u"Р", u"С", u"Т", u"У", u"Ф", u"'"], [u">", u"Х", u"Ц", u"Ч", u"Ш", u"Щ", u"Ъ", u"Ы", u";", u":", u"_", u"CLEAR"], [u"SHIFT", u"SPACE", u"?", u"\\", u"Ь", u"Э", u"Ю", u"Я", u"OK", u"LEFT", u"RIGHT"]] self.nextLang = 'sk_SK' elif self.lang =='sk_SK': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"ú", u"+"], [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ľ", u"@", u"#"], [u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL"], [u"SHIFT", u"SPACE", u"š", u"č", u"ž", u"ý", u"á", u"í", u"é", u"OK", u"LEFT", u"RIGHT"]] self.shiftkeys_list = [ [u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE"], [u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"ť", u"*"], [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"ň", u"ď", u"'"], [u"Á", u"É", u"Ď", u"Í", u"Ý", u"Ó", u"Ú", u"Ž", u"Š", u"Č", u"Ť", u"Ň"], [u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR"], [u"SHIFT", u"SPACE", u"?", u"\\", u"ä", u"ö", u"ü", u"ô", u"ŕ", u"ĺ", u"OK"]] self.nextLang = 'sv_SE' elif self.lang == 'sv_SE': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"é", u"+"], [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ö", u"ä", u"#"], [u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL"], [u"SHIFT", u"SPACE", u"@", u"ß", u"ĺ", u"OK", u"LEFT", u"RIGHT"]] self.shiftkeys_list = [ [u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE"], [u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"É", u"*"], [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"Ö", u"Ä", u"'"], [u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR"], [u"SHIFT", u"SPACE", u"?", u"\\", u"Ĺ", u"OK", u"LEFT", u"RIGHT"]] self.nextLang = 'th_TH' elif self.lang == 'th_TH': self.keys_list = [[u"EXIT", "\xe0\xb9\x85", "\xe0\xb8\xa0", "\xe0\xb8\x96", "\xe0\xb8\xb8", "\xe0\xb8\xb6", "\xe0\xb8\x84", "\xe0\xb8\x95", "\xe0\xb8\x88", "\xe0\xb8\x82", "\xe0\xb8\x8a", u"BACKSPACE"], ["\xe0\xb9\x86", "\xe0\xb9\x84", "\xe0\xb8\xb3", "\xe0\xb8\x9e", "\xe0\xb8\xb0", "\xe0\xb8\xb1", "\xe0\xb8\xb5", "\xe0\xb8\xa3", "\xe0\xb8\x99", "\xe0\xb8\xa2", "\xe0\xb8\x9a", "\xe0\xb8\xa5"], ["\xe0\xb8\x9f", "\xe0\xb8\xab", "\xe0\xb8\x81", "\xe0\xb8\x94", "\xe0\xb9\x80", "\xe0\xb9\x89", "\xe0\xb9\x88", "\xe0\xb8\xb2", "\xe0\xb8\xaa", "\xe0\xb8\xa7", "\xe0\xb8\x87", "\xe0\xb8\x83"], ["\xe0\xb8\x9c", "\xe0\xb8\x9b", "\xe0\xb9\x81", "\xe0\xb8\xad", "\xe0\xb8\xb4", "\xe0\xb8\xb7", "\xe0\xb8\x97", "\xe0\xb8\xa1", "\xe0\xb9\x83", "\xe0\xb8\x9d", "", u"ALL"], [u"SHIFT", u"SPACE", u"OK", u"LEFT", u"RIGHT"]] self.shiftkeys_list = [[u"EXIT", "\xe0\xb9\x91", "\xe0\xb9\x92", "\xe0\xb9\x93", "\xe0\xb9\x94", "\xe0\xb8\xb9", "\xe0\xb9\x95", "\xe0\xb9\x96", "\xe0\xb9\x97", "\xe0\xb9\x98", "\xe0\xb9\x99", u"BACKSPACE"], ["\xe0\xb9\x90", "", "\xe0\xb8\x8e", "\xe0\xb8\x91", "\xe0\xb8\x98", "\xe0\xb9\x8d", "\xe0\xb9\x8a", "\xe0\xb8\x93", "\xe0\xb8\xaf", "\xe0\xb8\x8d", "\xe0\xb8\x90", "\xe0\xb8\x85"], ["\xe0\xb8\xa4", "\xe0\xb8\x86", "\xe0\xb8\x8f", "\xe0\xb9\x82", "\xe0\xb8\x8c", "\xe0\xb9\x87", "\xe0\xb9\x8b", "\xe0\xb8\xa9", "\xe0\xb8\xa8", "\xe0\xb8\x8b", "", "\xe0\xb8\xbf"], ["", "", "\xe0\xb8\x89", "\xe0\xb8\xae", "\xe0\xb8\xba", "\xe0\xb9\x8c", "", "\xe0\xb8\x92", "\xe0\xb8\xac", "\xe0\xb8\xa6", "", u"CLEAR"], [u"SHIFT", u"SPACE", u"OK", u"LEFT", u"RIGHT"]] self.nextLang = 'uk_UA' elif self.lang == 'uk_UA': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"а", u"б", u"в", u"г", u"ґ", u"д", u"е", u"є", u"ж", u"з", u"и", u"+"], [u"і", u"ї", u"й", u"к", u"л", u"м", u"н", u"о", u"п", u"р", u"с", u"#"], [u"<", u"т", u"у", u"ф", u"х", u"ц", u"ч", u"ш", u",", u".", u"-", u"ALL"], [u"SHIFT", u"SPACE", u"@", u"щ", u"ь", u"ю", u"я", u"OK", u"LEFT", u"RIGHT"]] self.shiftkeys_list = [ [u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE"], [u"А", u"Б", u"В", u"Г", u"Ґ", u"Д", u"Е", u"Є", u"Ж", u"З", u"И", u"*"], [u"І", u"Ї", u"Й", u"К", u"Л", u"М", u"Н", u"О", u"П", u"Р", u"С", u"'"], [u">", u"Т", u"У", u"Ф", u"Х", u"Ц", u"Ч", u"Ш", u";", u":", u"_", u"CLEAR"], [u"SHIFT", u"SPACE", u"?", u"\\", u"Щ", u"Ь", u"Ю", u"Я", u"OK", u"LEFT", u"RIGHT"]] self.nextLang = 'en_EN' else: self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"q", u"w", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"-", u"["], [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u";", u"'", u"\\"], [u"<", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"/", u"ALL"], [u"SHIFT", u"SPACE", u"OK", u"LEFT", u"RIGHT", u"*"]] self.shiftkeys_list = [ [u"EXIT", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"(", u")", u"=", u"BACKSPACE"], [u"Q", u"W", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"+", u"]"], [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"?", u'"', u"|"], [u">", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR"], [u"SHIFT", u"SPACE", u"OK", u"LEFT", u"RIGHT", u"~"]] self.lang = 'en_EN' self.nextLang = 'ar_AE' self["country"].setText(self.lang) self["key_yellow"].setText(language.lang[self.lang][0]) def virtualKeyBoardEntryComponent(self, keys): w, h = skin.parameters.get("VirtualKeyboard",(45, 45)) key_bg_width = self.key_bg and self.key_bg.size().width() or w key_images = self.shiftMode and self.keyImagesShift or self.keyImages res = [keys] text = [] x = 0 for key in keys: png = key_images.get(key, None) if png: width = png.size().width() res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, h), png=png)) else: width = key_bg_width res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, h), png=self.key_bg)) text.append(MultiContentEntryText(pos=(x, 0), size=(width, h), font=0, text=key.encode("utf-8"), flags=RT_HALIGN_CENTER | RT_VALIGN_CENTER)) x += width return res + text def buildVirtualKeyBoard(self): self.previousSelectedKey = None self.list = [] self.max_key = 0 for keys in self.shiftMode and self.shiftkeys_list or self.keys_list: self.list.append(self.virtualKeyBoardEntryComponent(keys)) self.max_key += len(keys) self.max_key -= 1 self.markSelectedKey() def markSelectedKey(self): w, h = skin.parameters.get("VirtualKeyboard",(45, 45)) if self.previousSelectedKey is not None: self.list[self.previousSelectedKey /12] = self.list[self.previousSelectedKey /12][:-1] width = self.key_sel.size().width() try: x = self.list[self.selectedKey/12][self.selectedKey % 12 + 1][1] except IndexError: self.selectedKey = self.max_key x = self.list[self.selectedKey/12][self.selectedKey % 12 + 1][1] self.list[self.selectedKey / 12].append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, h), png=self.key_sel)) self.previousSelectedKey = self.selectedKey self["list"].setList(self.list) def backClicked(self): self["text"].deleteBackward() def forwardClicked(self): self["text"].deleteForward() def shiftClicked(self): self.smsChar = None self.shiftMode = not self.shiftMode self.buildVirtualKeyBoard() def okClicked(self): self.smsChar = None text = (self.shiftMode and self.shiftkeys_list or self.keys_list)[self.selectedKey / 12][self.selectedKey % 12].encode("UTF-8") if text == "EXIT": self.close(None) elif text == "BACKSPACE": self["text"].deleteBackward() elif text == "ALL": self["text"].markAll() elif text == "CLEAR": self["text"].deleteAllChars() self["text"].update() elif text == "SHIFT": self.shiftClicked() elif text == "SPACE": self["text"].char(" ".encode("UTF-8")) elif text == "OK": self.close(self["text"].getText()) elif text == "LEFT": self["text"].left() elif text == "RIGHT": self["text"].right() else: self["text"].char(text) def ok(self): self.close(self["text"].getText()) def exit(self): self.close(None) def cursorRight(self): self["text"].right() def cursorLeft(self): self["text"].left() def left(self): self.smsChar = None self.selectedKey = self.selectedKey / 12 * 12 + (self.selectedKey + 11) % 12 if self.selectedKey > self.max_key: self.selectedKey = self.max_key self.markSelectedKey() def right(self): self.smsChar = None self.selectedKey = self.selectedKey / 12 * 12 + (self.selectedKey + 1) % 12 if self.selectedKey > self.max_key: self.selectedKey = self.selectedKey / 12 * 12 self.markSelectedKey() def up(self): self.smsChar = None self.selectedKey -= 12 if self.selectedKey < 0: self.selectedKey = self.max_key / 12 * 12 + self.selectedKey % 12 if self.selectedKey > self.max_key: self.selectedKey -= 12 self.markSelectedKey() def down(self): self.smsChar = None self.selectedKey += 12 if self.selectedKey > self.max_key: self.selectedKey %= 12 self.markSelectedKey() def keyNumberGlobal(self, number): self.smsChar = self.sms.getKey(number) self.selectAsciiKey(self.smsChar) def smsOK(self): if self.smsChar and self.selectAsciiKey(self.smsChar): print "pressing ok now" self.okClicked() def keyGotAscii(self): self.smsChar = None if self.selectAsciiKey(str(unichr(getPrevAsciiCode()).encode('utf-8'))): self.okClicked() def selectAsciiKey(self, char): if char == " ": char = "SPACE" for keyslist in (self.shiftkeys_list, self.keys_list): selkey = 0 for keys in keyslist: for key in keys: if key == char: self.selectedKey = selkey if self.shiftMode != (keyslist is self.shiftkeys_list): self.shiftMode = not self.shiftMode self.buildVirtualKeyBoard() else: self.markSelectedKey() return True selkey += 1 return False
class VirtualKeyBoard(Screen): def __init__(self, session, title='', **kwargs): Screen.__init__(self, session) self.setTitle(_('Virtual keyboard')) self.keys_list = [] self.shiftkeys_list = [] self.lang = language.getLanguage() self.nextLang = None self.shiftMode = False self.selectedKey = 0 self.smsChar = None self.sms = NumericalTextInput(self.smsOK) self.key_bg = LoadPixmap(path=resolveFilename( SCOPE_CURRENT_SKIN, 'skin_default/vkey_bg.png')) self.key_sel = LoadPixmap(path=resolveFilename( SCOPE_CURRENT_SKIN, 'skin_default/vkey_sel.png')) self.key_backspace = LoadPixmap(path=resolveFilename( SCOPE_CURRENT_SKIN, 'skin_default/vkey_backspace.png')) self.key_all = LoadPixmap(path=resolveFilename( SCOPE_CURRENT_SKIN, 'skin_default/vkey_all.png')) self.key_clr = LoadPixmap(path=resolveFilename( SCOPE_CURRENT_SKIN, 'skin_default/vkey_clr.png')) self.key_esc = LoadPixmap(path=resolveFilename( SCOPE_CURRENT_SKIN, 'skin_default/vkey_esc.png')) self.key_ok = LoadPixmap(path=resolveFilename( SCOPE_CURRENT_SKIN, 'skin_default/vkey_ok.png')) self.key_shift = LoadPixmap(path=resolveFilename( SCOPE_CURRENT_SKIN, 'skin_default/vkey_shift.png')) self.key_shift_sel = LoadPixmap(path=resolveFilename( SCOPE_CURRENT_SKIN, 'skin_default/vkey_shift_sel.png')) self.key_space = LoadPixmap(path=resolveFilename( SCOPE_CURRENT_SKIN, 'skin_default/vkey_space.png')) self.key_left = LoadPixmap(path=resolveFilename( SCOPE_CURRENT_SKIN, 'skin_default/vkey_left.png')) self.key_right = LoadPixmap(path=resolveFilename( SCOPE_CURRENT_SKIN, 'skin_default/vkey_right.png')) self.keyImages = { 'BACKSPACE': self.key_backspace, 'ALL': self.key_all, 'EXIT': self.key_esc, 'OK': self.key_ok, 'SHIFT': self.key_shift, 'SPACE': self.key_space, 'LEFT': self.key_left, 'RIGHT': self.key_right } self.keyImagesShift = { 'BACKSPACE': self.key_backspace, 'CLEAR': self.key_clr, 'EXIT': self.key_esc, 'OK': self.key_ok, 'SHIFT': self.key_shift_sel, 'SPACE': self.key_space, 'LEFT': self.key_left, 'RIGHT': self.key_right } self['country'] = StaticText('') self['header'] = Label(title) self['text'] = Input(currPos=len( kwargs.get('text', '').decode('utf-8', 'ignore')), allMarked=False, **kwargs) self['list'] = VirtualKeyBoardList([]) self['actions'] = NumberActionMap( [ 'OkCancelActions', 'WizardActions', 'ColorActions', 'KeyboardInputActions', 'InputBoxActions', 'InputAsciiActions' ], { 'gotAsciiCode': self.keyGotAscii, 'ok': self.okClicked, 'cancel': self.exit, 'left': self.left, 'right': self.right, 'up': self.up, 'down': self.down, 'red': self.exit, 'green': self.ok, 'yellow': self.switchLang, 'blue': self.shiftClicked, 'deleteBackward': self.backClicked, 'deleteForward': self.forwardClicked, 'back': self.exit, 'pageUp': self.cursorRight, 'pageDown': self.cursorLeft, '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 }, -2) self.setLang() self.onExecBegin.append(self.setKeyboardModeAscii) self.onLayoutFinish.append(self.buildVirtualKeyBoard) self.onClose.append(self.__onClose) def __onClose(self): self.sms.timer.stop() def switchLang(self): self.lang = self.nextLang self.setLang() self.buildVirtualKeyBoard() def setLang(self): if self.lang == 'de_DE': self.keys_list = [[ u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE' ], [ u'q', u'w', u'e', u'r', u't', u'z', u'u', u'i', u'o', u'p', u'\xfc', u'+' ], [ u'a', u's', u'd', u'f', u'g', u'h', u'j', u'k', u'l', u'\xf6', u'\xe4', u'#' ], [ u'<', u'y', u'x', u'c', u'v', u'b', u'n', u'm', u',', '.', u'-', u'ALL' ], [ u'SHIFT', u'SPACE', u'@', u'\xdf', u'OK', u'LEFT', u'RIGHT' ]] self.shiftkeys_list = [[ u'EXIT', u'!', u'"', u'\xa7', u'$', u'%', u'&', u'/', u'(', u')', u'=', u'BACKSPACE' ], [ u'Q', u'W', u'E', u'R', u'T', u'Z', u'U', u'I', u'O', u'P', u'\xdc', u'*' ], [ u'A', u'S', u'D', u'F', u'G', u'H', u'J', u'K', u'L', u'\xd6', u'\xc4', u"'" ], [ u'>', u'Y', u'X', u'C', u'V', u'B', u'N', u'M', u';', u':', u'_', u'CLEAR' ], [ u'SHIFT', u'SPACE', u'?', u'\\', u'OK', u'LEFT', u'RIGHT' ]] self.nextLang = 'ar_AE' elif self.lang == 'ar_AE': self.keys_list = [[ u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE' ], [ u'\u0636', u'\u0635', u'\u062b', u'\u0642', u'\u0641', u'\u063a', u'\u0639', u'\u0647', u'\u062e', u'\u062d', u'\u062c', u'\u062f' ], [ u'\u0634', u'\u0633', u'\u064a', u'\u0628', u'\u0644', u'\u0627', u'\u062a', u'\u0646', u'\u0645', u'\u0643', u'\u0637', u'\u0630' ], [ u'\u0626', u'\u0621', u'\u0624', u'\u0631', u'\u0644\u0627', u'\u0649', u'\u0629', u'\u0648', u'\u0632', '\xd8\xb8', u'#', u'ALL' ], [ u'SHIFT', u'SPACE', u'-', u'@', u'.', u'\u0644\u0622', u'\u0622', u'\u0644\u0623', u'\u0644\u0625', u'\u0625', u'\u0623', u'OK', u'LEFT', u'RIGHT' ]] self.shiftkeys_list = [[ u'EXIT', u'!', u'"', u'\xa7', u'$', u'^', u'<', u'>', u'(', u')', u'=', u'BACKSPACE' ], [ u'\u064e', u'\u064b', u'\u064f', u'\u064c', u'%', u'\u060c', u'\u2018', u'\xf7', u'\xd7', u'\u061b', u'<', u'>' ], [ u'\u0650', u'\u064d', u']', u'[', u'*', u'+', u'\u0640', u'\u060c', u'/', u':', u'~', u"'" ], [ u'\u0652', u'}', u'{', u'-', u'/', u'\u2019', u',', u'.', u'\u061f', u':', u'_', u'CLEAR' ], [ u'SHIFT', u'SPACE', u'?', u'\\', u'=', u'\u0651', u'~', u'OK', u'LEFT', u'RIGHT' ]] self.nextLang = 'es_ES' elif self.lang == 'es_ES': self.keys_list = [[ u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE' ], [ u'q', u'w', u'e', u'r', u't', u'z', u'u', u'i', u'o', u'p', u'\xfa', u'+' ], [ u'a', u's', u'd', u'f', u'g', u'h', u'j', u'k', u'l', u'\xf3', u'\xe1', u'#' ], [ u'<', u'y', u'x', u'c', u'v', u'b', u'n', u'm', u',', '.', u'-', u'ALL' ], [ u'SHIFT', u'SPACE', u'@', u'\u0141', u'\u0155', u'\xe9', u'\u010d', u'\xed', u'\u011b', u'\u0144', u'\u0148', u'OK' ]] self.shiftkeys_list = [[ u'EXIT', u'!', u'"', u'\xa7', u'$', u'%', u'&', u'/', u'(', u')', u'=', u'BACKSPACE' ], [ u'Q', u'W', u'E', u'R', u'T', u'Z', u'U', u'I', u'O', u'P', u'\xda', u'*' ], [ u'A', u'S', u'D', u'F', u'G', u'H', u'J', u'K', u'L', u'\xd3', u'\xc1', u"'" ], [ u'>', u'Y', u'X', u'C', u'V', u'B', u'N', u'M', u';', u':', u'_', u'CLEAR' ], [ u'SHIFT', u'SPACE', u'?', u'\\', u'\u0154', u'\xc9', u'\u010c', u'\xcd', u'\u011a', u'\u0143', u'\u0147', u'OK' ]] self.nextLang = 'fi_FI' elif self.lang == 'fi_FI': self.keys_list = [[ u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE' ], [ u'q', u'w', u'e', u'r', u't', u'z', u'u', u'i', u'o', u'p', u'\xe9', u'+' ], [ u'a', u's', u'd', u'f', u'g', u'h', u'j', u'k', u'l', u'\xf6', u'\xe4', u'#' ], [ u'<', u'y', u'x', u'c', u'v', u'b', u'n', u'm', u',', '.', u'-', u'ALL' ], [ u'SHIFT', u'SPACE', u'@', u'\xdf', u'\u013a', u'OK', u'LEFT', u'RIGHT' ]] self.shiftkeys_list = [[ u'EXIT', u'!', u'"', u'\xa7', u'$', u'%', u'&', u'/', u'(', u')', u'=', u'BACKSPACE' ], [ u'Q', u'W', u'E', u'R', u'T', u'Z', u'U', u'I', u'O', u'P', u'\xc9', u'*' ], [ u'A', u'S', u'D', u'F', u'G', u'H', u'J', u'K', u'L', u'\xd6', u'\xc4', u"'" ], [ u'>', u'Y', u'X', u'C', u'V', u'B', u'N', u'M', u';', u':', u'_', u'CLEAR' ], [ u'SHIFT', u'SPACE', u'?', u'\\', u'\u0139', u'OK', u'LEFT', u'RIGHT' ]] self.nextLang = 'lv_LV' elif self.lang == 'lv_LV': self.keys_list = [[ u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE' ], [ u'q', u'w', u'e', u'r', u't', u'y', u'u', u'i', u'o', u'p', u'-', u'\u0161' ], [ u'a', u's', u'd', u'f', u'g', u'h', u'j', u'k', u'l', u';', u"'", u'\u016b' ], [ u'<', u'z', u'x', u'c', u'v', u'b', u'n', u'm', u',', u'.', u'\u017e', u'ALL' ], [ u'SHIFT', u'SPACE', u'\u0101', u'\u010d', u'\u0113', u'\u0123', u'\u012b', u'\u0137', u'\u013c', u'\u0146', u'LEFT', u'RIGHT' ]] self.shiftkeys_list = [[ u'EXIT', u'!', u'@', u'$', u'*', u'(', u')', u'_', u'=', u'/', u'\\', u'BACKSPACE' ], [ u'Q', u'W', u'E', u'R', u'T', u'Y', u'U', u'I', u'O', u'P', u'+', u'\u0160' ], [ u'A', u'S', u'D', u'F', u'G', u'H', u'J', u'K', u'L', u':', u'"', u'\u016a' ], [ u'>', u'Z', u'X', u'C', u'V', u'B', u'N', u'M', u'#', u'?', u'\u017d', u'CLEAR' ], [ u'SHIFT', u'SPACE', u'\u0100', u'\u010c', u'\u0112', u'\u0122', u'\u012a', u'\u0136', u'\u013b', u'\u0145', u'LEFT', u'RIGHT' ]] self.nextLang = 'ru_RU' elif self.lang == 'ru_RU': self.keys_list = [[ u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE' ], [ u'\u0430', u'\u0431', u'\u0432', u'\u0433', u'\u0434', u'\u0435', u'\u0451', u'\u0436', u'\u0437', u'\u0438', u'\u0439', u'+' ], [ u'\u043a', u'\u043b', u'\u043c', u'\u043d', u'\u043e', u'\u043f', u'\u0440', u'\u0441', u'\u0442', u'\u0443', u'\u0444', u'#' ], [ u'<', u'\u0445', u'\u0446', u'\u0447', u'\u0448', u'\u0449', u'\u044a', u'\u044b', u',', u'.', u'-', u'ALL' ], [ u'SHIFT', u'SPACE', u'@', u'\u044c', u'\u044d', u'\u044e', u'\u044f', u'OK', u'LEFT', u'RIGHT' ]] self.shiftkeys_list = [[ u'EXIT', u'!', u'"', u'\xa7', u'$', u'%', u'&', u'/', u'(', u')', u'=', u'BACKSPACE' ], [ u'\u0410', u'\u0411', u'\u0412', u'\u0413', u'\u0414', u'\u0415', u'\u0401', u'\u0416', u'\u0417', u'\u0418', u'\u0419', u'*' ], [ u'\u041a', u'\u041b', u'\u041c', u'\u041d', u'\u041e', u'\u041f', u'\u0420', u'\u0421', u'\u0422', u'\u0423', u'\u0424', u"'" ], [ u'>', u'\u0425', u'\u0426', u'\u0427', u'\u0428', u'\u0429', u'\u042a', u'\u042b', u';', u':', u'_', u'CLEAR' ], [ u'SHIFT', u'SPACE', u'?', u'\\', u'\u042c', u'\u042d', u'\u042e', u'\u042f', u'OK', u'LEFT', u'RIGHT' ]] self.nextLang = 'sv_SE' elif self.lang == 'sv_SE': self.keys_list = [[ u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE' ], [ u'q', u'w', u'e', u'r', u't', u'z', u'u', u'i', u'o', u'p', u'\xe9', u'+' ], [ u'a', u's', u'd', u'f', u'g', u'h', u'j', u'k', u'l', u'\xf6', u'\xe4', u'#' ], [ u'<', u'y', u'x', u'c', u'v', u'b', u'n', u'm', u',', '.', u'-', u'ALL' ], [ u'SHIFT', u'SPACE', u'@', u'\xdf', u'\u013a', u'OK', u'LEFT', u'RIGHT' ]] self.shiftkeys_list = [[ u'EXIT', u'!', u'"', u'\xa7', u'$', u'%', u'&', u'/', u'(', u')', u'=', u'BACKSPACE' ], [ u'Q', u'W', u'E', u'R', u'T', u'Z', u'U', u'I', u'O', u'P', u'\xc9', u'*' ], [ u'A', u'S', u'D', u'F', u'G', u'H', u'J', u'K', u'L', u'\xd6', u'\xc4', u"'" ], [ u'>', u'Y', u'X', u'C', u'V', u'B', u'N', u'M', u';', u':', u'_', u'CLEAR' ], [ u'SHIFT', u'SPACE', u'?', u'\\', u'\u0139', u'OK', u'LEFT', u'RIGHT' ]] self.nextLang = 'sk_SK' elif self.lang == 'sk_SK': self.keys_list = [[ u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE' ], [ u'q', u'w', u'e', u'r', u't', u'z', u'u', u'i', u'o', u'p', u'\xfa', u'+' ], [ u'a', u's', u'd', u'f', u'g', u'h', u'j', u'k', u'l', u'\u013e', u'@', u'#' ], [ u'<', u'y', u'x', u'c', u'v', u'b', u'n', u'm', u',', '.', u'-', u'ALL' ], [ u'SHIFT', u'SPACE', u'\u0161', u'\u010d', u'\u017e', u'\xfd', u'\xe1', u'\xed', u'\xe9', u'OK', u'LEFT', u'RIGHT' ]] self.shiftkeys_list = [[ u'EXIT', u'!', u'"', u'\xa7', u'$', u'%', u'&', u'/', u'(', u')', u'=', u'BACKSPACE' ], [ u'Q', u'W', u'E', u'R', u'T', u'Z', u'U', u'I', u'O', u'P', u'\u0165', u'*' ], [ u'A', u'S', u'D', u'F', u'G', u'H', u'J', u'K', u'L', u'\u0148', u'\u010f', u"'" ], [ u'\xc1', u'\xc9', u'\u010e', u'\xcd', u'\xdd', u'\xd3', u'\xda', u'\u017d', u'\u0160', u'\u010c', u'\u0164', u'\u0147' ], [ u'>', u'Y', u'X', u'C', u'V', u'B', u'N', u'M', u';', u':', u'_', u'CLEAR' ], [ u'SHIFT', u'SPACE', u'?', u'\\', u'\xe4', u'\xf6', u'\xfc', u'\xf4', u'\u0155', u'\u013a', u'OK' ]] self.nextLang = 'cs_CZ' elif self.lang == 'cs_CZ': self.keys_list = [[ u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE' ], [ u'q', u'w', u'e', u'r', u't', u'z', u'u', u'i', u'o', u'p', u'\xfa', u'+' ], [ u'a', u's', u'd', u'f', u'g', u'h', u'j', u'k', u'l', u'\u016f', u'@', u'#' ], [ u'<', u'y', u'x', u'c', u'v', u'b', u'n', u'm', u',', '.', u'-', u'ALL' ], [ u'SHIFT', u'SPACE', u'\u011b', u'\u0161', u'\u010d', u'\u0159', u'\u017e', u'\xfd', u'\xe1', u'\xed', u'\xe9', u'OK' ]] self.shiftkeys_list = [[ u'EXIT', u'!', u'"', u'\xa7', u'$', u'%', u'&', u'/', u'(', u')', u'=', u'BACKSPACE' ], [ u'Q', u'W', u'E', u'R', u'T', u'Z', u'U', u'I', u'O', u'P', u'\u0165', u'*' ], [ u'A', u'S', u'D', u'F', u'G', u'H', u'J', u'K', u'L', u'\u0148', u'\u010f', u"'" ], [ u'>', u'Y', u'X', u'C', u'V', u'B', u'N', u'M', u';', u':', u'_', u'CLEAR' ], [ u'SHIFT', u'SPACE', u'?', u'\\', u'\u010c', u'\u0158', u'\u0160', u'\u017d', u'\xda', u'\xc1', u'\xc9', u'OK' ]] self.nextLang = 'el_GR' elif self.lang == 'el_GR': self.keys_list = [[ u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE' ], [ u'=', u'\u03c2', u'\u03b5', u'\u03c1', u'\u03c4', u'\u03c5', u'\u03b8', u'\u03b9', u'\u03bf', u'\u03c0', u'[', u']' ], [ u'\u03b1', u'\u03c3', u'\u03b4', u'\u03c6', u'\u03b3', u'\u03b7', u'\u03be', u'\u03ba', u'\u03bb', u';', u"'", u'-' ], [ u'\\', u'\u03b6', u'\u03c7', u'\u03c8', u'\u03c9', u'\u03b2', u'\u03bd', u'\u03bc', u',', '.', u'/', u'ALL' ], [ u'SHIFT', u'SPACE', u'\u03ac', u'\u03ad', u'\u03ae', u'\u03af', u'\u03cc', u'\u03cd', u'\u03ce', u'\u03ca', u'\u03cb', u'OK' ]] self.shiftkeys_list = [[ u'EXIT', u'!', u'@', u'#', u'$', u'%', u'^', u'&', u'*', u'(', u')', u'BACKSPACE' ], [ u'+', u'\u20ac', u'\u0395', u'\u03a1', u'\u03a4', u'\u03a5', u'\u0398', u'\u0399', u'\u039f', u'\u03a0', u'{', u'}' ], [ u'\u0391', u'\u03a3', u'\u0394', u'\u03a6', u'\u0393', u'\u0397', u'\u039e', u'\u039a', u'\u039b', u':', u'"', u'_' ], [ u'|', u'\u0396', u'\u03a7', u'\u03a8', u'\u03a9', u'\u0392', u'\u039d', u'\u039c', u'<', u'>', u'?', u'CLEAR' ], [ u'SHIFT', u'SPACE', u'\u0386', u'\u0388', u'\u0389', u'\u038a', u'\u038c', u'\u038e', u'\u038f', u'\u03aa', u'\u03ab', u'OK' ]] self.nextLang = 'pl_PL' elif self.lang == 'pl_PL': self.keys_list = [[ u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE' ], [ u'q', u'w', u'e', u'r', u't', u'y', u'u', u'i', u'o', u'p', u'-', u'[' ], [ u'a', u's', u'd', u'f', u'g', u'h', u'j', u'k', u'l', u';', u"'", u'\\' ], [ u'<', u'z', u'x', u'c', u'v', u'b', u'n', u'm', u',', '.', u'/', u'ALL' ], [ u'SHIFT', u'SPACE', u'\u0105', u'\u0107', u'\u0119', u'\u0142', u'\u0144', u'\xf3', u'\u015b', u'\u017a', u'\u017c', u'OK' ]] self.shiftkeys_list = [[ u'EXIT', u'!', u'@', u'#', u'$', u'%', u'^', u'&', u'(', u')', u'=', u'BACKSPACE' ], [ u'Q', u'W', u'E', u'R', u'T', u'Y', u'U', u'I', u'O', u'P', u'*', u']' ], [ u'A', u'S', u'D', u'F', u'G', u'H', u'J', u'K', u'L', u'?', u'"', u'|' ], [ u'>', u'Z', u'X', u'C', u'V', u'B', u'N', u'M', u';', u':', u'_', u'CLEAR' ], [ u'SHIFT', u'SPACE', u'\u0104', u'\u0106', u'\u0118', u'\u0141', u'\u0143', u'\xd3', u'\u015a', u'\u0179', u'\u017b', u'OK' ]] self.nextLang = 'en_EN' else: self.keys_list = [[ u'EXIT', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'0', u'BACKSPACE' ], [ u'q', u'w', u'e', u'r', u't', u'y', u'u', u'i', u'o', u'p', u'-', u'[' ], [ u'a', u's', u'd', u'f', u'g', u'h', u'j', u'k', u'l', u';', u"'", u'\\' ], [ u'<', u'z', u'x', u'c', u'v', u'b', u'n', u'm', u',', '.', u'/', u'ALL' ], [ u'SHIFT', u'SPACE', u'OK', u'LEFT', u'RIGHT', u'*' ]] self.shiftkeys_list = [[ u'EXIT', u'!', u'@', u'#', u'$', u'%', u'^', u'&', u'(', u')', u'=', u'BACKSPACE' ], [ u'Q', u'W', u'E', u'R', u'T', u'Y', u'U', u'I', u'O', u'P', u'+', u']' ], [ u'A', u'S', u'D', u'F', u'G', u'H', u'J', u'K', u'L', u'?', u'"', u'|' ], [ u'>', u'Z', u'X', u'C', u'V', u'B', u'N', u'M', u';', u':', u'_', u'CLEAR' ], [ u'SHIFT', u'SPACE', u'OK', u'LEFT', u'RIGHT', u'~' ]] self.lang = 'en_EN' self.nextLang = 'de_DE' self['country'].setText(self.lang) self.max_key = 47 + len(self.keys_list[4]) def virtualKeyBoardEntryComponent(self, keys): w, h = skin.parameters.get('VirtualKeyboard', (45, 45)) key_bg_width = self.key_bg and self.key_bg.size().width() or w key_images = self.shiftMode and self.keyImagesShift or self.keyImages res = [keys] text = [] x = 0 for key in keys: png = key_images.get(key, None) if png: width = png.size().width() res.append( MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, h), png=png)) else: width = key_bg_width res.append( MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, h), png=self.key_bg)) text.append( MultiContentEntryText(pos=(x, 0), size=(width, h), font=0, text=key.encode('utf-8'), flags=RT_HALIGN_CENTER | RT_VALIGN_CENTER)) x += width return res + text def buildVirtualKeyBoard(self): self.previousSelectedKey = None self.list = [] for keys in self.shiftMode and self.shiftkeys_list or self.keys_list: self.list.append(self.virtualKeyBoardEntryComponent(keys)) self.markSelectedKey() def markSelectedKey(self): w, h = skin.parameters.get('VirtualKeyboard', (45, 45)) if self.previousSelectedKey is not None: self.list[self.previousSelectedKey / 12] = self.list[self.previousSelectedKey / 12][:-1] width = self.key_sel.size().width() x = self.list[self.selectedKey / 12][self.selectedKey % 12 + 1][1] self.list[self.selectedKey / 12].append( MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, h), png=self.key_sel)) self.previousSelectedKey = self.selectedKey self['list'].setList(self.list) def backClicked(self): self['text'].deleteBackward() def forwardClicked(self): self['text'].deleteForward() def shiftClicked(self): self.smsChar = None self.shiftMode = not self.shiftMode self.buildVirtualKeyBoard() def okClicked(self): self.smsChar = None text = (self.shiftMode and self.shiftkeys_list or self.keys_list)[self.selectedKey / 12][self.selectedKey % 12].encode('UTF-8') if text == 'EXIT': self.close(None) elif text == 'BACKSPACE': self['text'].deleteBackward() elif text == 'ALL': self['text'].markAll() elif text == 'CLEAR': self['text'].deleteAllChars() self['text'].update() elif text == 'SHIFT': self.shiftClicked() elif text == 'SPACE': self['text'].char(' '.encode('UTF-8')) elif text == 'OK': self.close(self['text'].getText()) elif text == 'LEFT': self['text'].left() elif text == 'RIGHT': self['text'].right() else: self['text'].char(text) def ok(self): self.close(self['text'].getText()) def exit(self): self.close(None) def cursorRight(self): self['text'].right() def cursorLeft(self): self['text'].left() def left(self): self.smsChar = None self.selectedKey = self.selectedKey / 12 * 12 + (self.selectedKey + 11) % 12 if self.selectedKey > self.max_key: self.selectedKey = self.max_key self.markSelectedKey() def right(self): self.smsChar = None self.selectedKey = self.selectedKey / 12 * 12 + (self.selectedKey + 1) % 12 if self.selectedKey > self.max_key: self.selectedKey = self.selectedKey / 12 * 12 self.markSelectedKey() def up(self): self.smsChar = None self.selectedKey -= 12 if self.selectedKey < 0: self.selectedKey = self.max_key / 12 * 12 + self.selectedKey % 12 if self.selectedKey > self.max_key: self.selectedKey -= 12 self.markSelectedKey() def down(self): self.smsChar = None self.selectedKey += 12 if self.selectedKey > self.max_key: self.selectedKey = self.selectedKey % 12 self.markSelectedKey() def keyNumberGlobal(self, number): self.smsChar = self.sms.getKey(number) self.selectAsciiKey(self.smsChar) def smsOK(self): if self.smsChar and self.selectAsciiKey(self.smsChar): print 'pressing ok now' self.okClicked() def keyGotAscii(self): self.smsChar = None if self.selectAsciiKey(str(unichr( getPrevAsciiCode()).encode('utf-8'))): self.okClicked() def selectAsciiKey(self, char): if char == ' ': char = 'SPACE' for keyslist in (self.shiftkeys_list, self.keys_list): selkey = 0 for keys in keyslist: for key in keys: if key == char: self.selectedKey = selkey if self.shiftMode != (keyslist is self.shiftkeys_list): self.shiftMode = not self.shiftMode self.buildVirtualKeyBoard() else: self.markSelectedKey() return True selkey += 1 return False
class TimerList(HTMLComponent, GUIComponent, object): def buildTimerEntry(self, timer, processed): height = self.l.getItemSize().height() width = self.l.getItemSize().width() res = [None] serviceName = ' ' + timer.service_ref.getServiceName() serviceNameWidth = getTextBoundarySize(self.instance, self.serviceNameFont, self.l.getItemSize(), serviceName).width() if 200 > width - serviceNameWidth - self.iconWidth - self.iconMargin: serviceNameWidth = width - 200 - self.iconWidth - self.iconMargin res.append( (eListboxPythonMultiContent.TYPE_TEXT, width - serviceNameWidth, 0, serviceNameWidth, self.rowSplit, 0, RT_HALIGN_RIGHT | RT_VALIGN_BOTTOM, serviceName)) res.append( (eListboxPythonMultiContent.TYPE_TEXT, self.iconWidth + self.iconMargin, 0, width - serviceNameWidth - self.iconWidth - self.iconMargin, self.rowSplit, 2, RT_HALIGN_LEFT | RT_VALIGN_BOTTOM, timer.name)) begin = FuzzyTime(timer.begin) if timer.repeated: days = (_('Mon'), _('Tue'), _('Wed'), _('Thu'), _('Fri'), _('Sat'), _('Sun')) repeatedtext = [] flags = timer.repeated for x in (0, 1, 2, 3, 4, 5, 6): if flags & 1 == 1: repeatedtext.append(days[x]) flags >>= 1 if repeatedtext == [ _('Mon'), _('Tue'), _('Wed'), _('Thu'), _('Fri'), _('Sat'), _('Sun') ]: repeatedtext = _('Everyday') elif repeatedtext == [ _('Mon'), _('Tue'), _('Wed'), _('Thu'), _('Fri') ]: repeatedtext = _('Weekday') elif repeatedtext == [_('Sat'), _('Sun')]: repeatedtext = _('Weekend') else: repeatedtext = ', '.join(repeatedtext) if self.iconRepeat: res.append( (eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, self.iconMargin / 2, self.rowSplit + (self.itemHeight - self.rowSplit - self.iconHeight) / 2, self.iconWidth, self.iconHeight, self.iconRepeat)) else: repeatedtext = begin[0] if timer.justplay: if timer.end > timer.begin + 3: text = repeatedtext + (' %s ... %s (' + _('ZAP') + ', %d ' + _( 'mins') + ')') % (begin[1], FuzzyTime(timer.end)[1], (timer.end - timer.begin) / 60) else: text = repeatedtext + (' %s (' + _('ZAP') + ')') % begin[1] else: text = repeatedtext + (' %s ... %s (%d ' + _('mins') + ')') % (begin[1], FuzzyTime(timer.end)[1], (timer.end - timer.begin) / 60) icon = None if not processed: if timer.state == TimerEntry.StateWaiting: state = _('waiting') if timer.isAutoTimer: icon = self.iconAutoTimer else: icon = self.iconWait elif timer.state == TimerEntry.StatePrepared: state = _('about to start') icon = self.iconPrepared elif timer.state == TimerEntry.StateRunning: if timer.justplay: state = _('zapped') icon = self.iconZapped else: state = _('recording...') icon = self.iconRecording elif timer.state == TimerEntry.StateEnded: state = _('done!') icon = self.iconDone else: state = _('<unknown>') icon = None elif timer.disabled: state = _('disabled') icon = self.iconDisabled elif timer.failed: state = _('failed') icon = self.iconFailed else: state = _('done!') icon = self.iconDone icon and res.append( (eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, self.iconMargin / 2, (self.rowSplit - self.iconHeight) / 2, self.iconWidth, self.iconHeight, icon)) orbpos = self.getOrbitalPos(timer.service_ref) orbposWidth = getTextBoundarySize(self.instance, self.font, self.l.getItemSize(), orbpos).width() res.append( (eListboxPythonMultiContent.TYPE_TEXT, self.satPosLeft, self.rowSplit, orbposWidth, self.itemHeight - self.rowSplit, 1, RT_HALIGN_LEFT | RT_VALIGN_TOP, orbpos)) res.append((eListboxPythonMultiContent.TYPE_TEXT, self.iconWidth + self.iconMargin, self.rowSplit, self.satPosLeft - self.iconWidth - self.iconMargin, self.itemHeight - self.rowSplit, 1, RT_HALIGN_LEFT | RT_VALIGN_TOP, state)) res.append((eListboxPythonMultiContent.TYPE_TEXT, self.satPosLeft + orbposWidth, self.rowSplit, width - self.satPosLeft - orbposWidth, self.itemHeight - self.rowSplit, 1, RT_HALIGN_RIGHT | RT_VALIGN_TOP, text)) line = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, 'div-h.png')) res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, 0, height - 2, width, 2, line)) return res def __init__(self, list): GUIComponent.__init__(self) self.l = eListboxPythonMultiContent() self.l.setBuildFunc(self.buildTimerEntry) self.serviceNameFont = gFont('Regular', 20) self.font = gFont('Regular', 18) self.eventNameFont = gFont('Regular', 18) self.l.setList(list) self.itemHeight = 50 self.rowSplit = 25 self.iconMargin = 4 self.satPosLeft = 160 self.iconWait = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/timer_wait.png')) self.iconWidth = self.iconWait.size().width() self.iconHeight = self.iconWait.size().height() self.iconRecording = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/timer_rec.png')) self.iconPrepared = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/timer_prep.png')) self.iconDone = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/timer_done.png')) self.iconRepeat = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/timer_rep.png')) self.iconZapped = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/timer_zap.png')) self.iconDisabled = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/timer_off.png')) self.iconFailed = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/timer_failed.png')) self.iconAutoTimer = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/timer_autotimer.png')) def applySkin(self, desktop, parent): def itemHeight(value): self.itemHeight = int(value) def setServiceNameFont(value): self.serviceNameFont = parseFont(value, ((1, 1), (1, 1))) def setEventNameFont(value): self.eventNameFont = parseFont(value, ((1, 1), (1, 1))) def setFont(value): self.font = parseFont(value, ((1, 1), (1, 1))) def rowSplit(value): self.rowSplit = int(value) def iconMargin(value): self.iconMargin = int(value) def satPosLeft(value): self.satPosLeft = int(value) for attrib, value in list(self.skinAttributes): try: locals().get(attrib)(value) self.skinAttributes.remove((attrib, value)) except: pass self.l.setItemHeight(self.itemHeight) self.l.setFont(0, self.serviceNameFont) self.l.setFont(1, self.font) self.l.setFont(2, self.eventNameFont) return GUIComponent.applySkin(self, desktop, parent) def getCurrent(self): cur = self.l.getCurrentSelection() return cur and cur[0] GUI_WIDGET = eListbox def postWidgetCreate(self, instance): instance.setContent(self.l) self.instance = instance instance.setWrapAround(True) def moveToIndex(self, index): self.instance.moveSelectionTo(index) def getCurrentIndex(self): return self.instance.getCurrentIndex() currentIndex = property(getCurrentIndex, moveToIndex) currentSelection = property(getCurrent) def moveDown(self): self.instance.moveSelection(self.instance.moveDown) def invalidate(self): self.l.invalidate() def entryRemoved(self, idx): self.l.entryRemoved(idx) def getOrbitalPos(self, ref): refstr = None if hasattr(ref, 'sref'): refstr = str(ref.sref) else: refstr = str(ref) refstr = refstr and GetWithAlternative(refstr) if '%3a//' in refstr: return '%s' % _('Stream') else: op = int(refstr.split(':', 10)[6][:-4] or '0', 16) if op == 61166: return '%s' % _('DVB-T') if op == 65535: return '%s' % _('DVB-C') direction = 'E' if op > 1800: op = 3600 - op direction = 'W' return '%d.%d\xc2\xb0%s' % (op // 10, op % 10, direction)
class EpgCenterList(GUIComponent): # some static stuff used by ["list"] and ["upcoming"] widgets infoBarInstance = None eServiceCenterInstance = None bouquetList = [] bouquetServices = [] currentBouquetIndex = 0 bouquetIndexRanges = [] allServicesNameDict = {} recordTimer = None lenChannelDigits = 0 def __init__(self, blinkTimer, listType, videoMode, piconLoader, bouquetList, currentIndex, piconSize, listStyle, epgList): self.blinkTimer = blinkTimer self.listType = listType self.videoMode = videoMode self.piconLoader = piconLoader self.piconSize = piconSize self.baseHeight = self.piconSize.height() self.listStyle = listStyle self.epgList = epgList GUIComponent.__init__(self) from Screens.InfoBar import InfoBar EpgCenterList.infoBarInstance = InfoBar.instance EpgCenterList.eServiceCenterInstance = eServiceCenter.getInstance() self.l = eListboxPythonMultiContent() self.l.setBuildFunc(self.buildEpgEntry) self.onSelectionChanged = [ ] if self.videoMode == MODE_SD or self.videoMode == MODE_XD: self.overallFontHeight = 36 elif self.videoMode == MODE_HD: self.overallFontHeight = 44 #initialize self.list = [] self.mode = None self.similarShown = False config.plugins.merlinEpgCenter.listItemHeight.addNotifier(self.changeHeight, initial_call = True) config.plugins.merlinEpgCenter.adjustFontSize.addNotifier(self.setFontSizes, initial_call = True) if listType == LIST_TYPE_EPG: EpgCenterList.bouquetList = bouquetList EpgCenterList.currentBouquetIndex = currentIndex EpgCenterList.updateBouquetServices() EpgCenterList.recordTimer = NavigationInstance.instance.RecordTimer # zap timer pixmaps self.zap_pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/zap.png")) self.zap_pre_pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/zap_pre.png")) self.zap_post_pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/zap_post.png")) self.zap_event_pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/zap_event.png")) self.zap_repeated_pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/zap_repeated.png")) self.zap_add_pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/zap_add.png")) # record timer pixmaps self.timer_pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/timer.png")) self.timer_pre_pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/timer_pre.png")) self.timer_post_pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/timer_post.png")) self.timer_event_pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/timer_event.png")) self.timer_repeated_pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/timer_repeated.png")) self.timer_add_pixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/timer_add.png")) # progress pixmaps self.progressPixmap = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/Progress.png")) self.progressPixmap_0 = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/Progress_0.png")) self.progressPixmap_1 = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/Progress_1.png")) self.progressPixmap_2 = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/Progress_2.png")) self.progressPixmap_3 = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/Progress_3.png")) self.progressPixmap_4 = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_PLUGIN, "Extensions/MerlinEPGCenter/images/Progress_4.png")) self.progressPixmapWidth = self.progressPixmap.size().width() self.epgcache = eEPGCache.getInstance() self.blinkTimer.callbacks.append(self.invalidateList) def onShow(self): self.maxWidth = self.l.getItemSize().width() def setFontSizes(self, configElement = None): diff = configElement.getValue() if self.videoMode == MODE_SD: self.l.setFont(0, gFont("Regular", 18 + diff)) self.l.setFont(1, gFont("Regular", 16 + diff)) self.l.setFont(2, gFont("Regular", 14 + diff)) self.l.setFont(3, gFont("Regular", 12 + diff)) elif self.videoMode == MODE_XD: self.l.setFont(0, gFont("Regular", 18 + diff)) self.l.setFont(1, gFont("Regular", 16 + diff)) self.l.setFont(2, gFont("Regular", 14 + diff)) self.l.setFont(3, gFont("Regular", 12 + diff)) elif self.videoMode == MODE_HD: self.l.setFont(0, gFont("Regular", 22 + diff)) self.l.setFont(1, gFont("Regular", 20 + diff)) self.l.setFont(2, gFont("Regular", 18 + diff)) self.l.setFont(3, gFont("Regular", 16 + diff)) def setMaxWidth(self, newSize): self.maxWidth = newSize.width() def changeHeight(self, configElement = None): self.listStyle = config.plugins.merlinEpgCenter.listStyle.value if self.listStyle == STYLE_SINGLE_LINE: self.singleLineBorder = 2 else: self.singleLineBorder = 0 if self.listStyle == STYLE_SHORT_DESCRIPTION or (self.listStyle == STYLE_SINGLE_LINE and (self.mode == SINGLE_EPG or self.mode == EPGSEARCH_RESULT or self.similarShown)): if self.overallFontHeight > self.baseHeight: self.itemHeight = self.overallFontHeight + int(config.plugins.merlinEpgCenter.listItemHeight.value) else: self.itemHeight = self.baseHeight + int(config.plugins.merlinEpgCenter.listItemHeight.value) elif self.videoMode == MODE_HD and config.plugins.merlinEpgCenter.listProgressStyle.value == STYLE_PERCENT_TEXT: # HD skin adjustment for text size self.itemHeight = self.baseHeight + int(config.plugins.merlinEpgCenter.listItemHeight.value) + 4 else: self.itemHeight = self.baseHeight + int(config.plugins.merlinEpgCenter.listItemHeight.value) self.halfItemHeight = self.itemHeight / 2 self.l.setItemHeight(self.itemHeight) def buildEpgEntry(self, ignoreMe, eventid, sRef, begin, duration, title, short, desc): columnSpace = config.plugins.merlinEpgCenter.columnSpace.getValue() progressPixmap = None offsetLeft = 5 offsetRight = self.maxWidth - 5 - 8 # 8 = timer pixmap width, 5 = border secondLineColor = 0x00909090 # grey border = int(config.plugins.merlinEpgCenter.listItemHeight.value) / 2 percent = 0 if begin != None and duration != None: timeString = strftime("%H:%M", localtime(begin)) + "-" + strftime("%H:%M", localtime(begin + duration)) now = int(time()) if now > begin: percent = (now - begin) * 100 / duration if self.mode == MULTI_EPG_NOW: timeValue = (begin + duration - now) / 60 +1 elif self.mode == MULTI_EPG_NEXT or self.mode == UPCOMING: timeValue = (now - begin) / 60 elif self.mode == MULTI_EPG_PRIMETIME or self.mode == EPGSEARCH_RESULT: if now >= begin: timeValue = (begin + duration - now) / 60 + 1 else: timeValue = (now - begin) / 60 elif self.mode == SINGLE_EPG: if self.instance.getCurrentIndex() == 0: timeValue = (begin + duration - now) / 60 + 1 else: timeValue = (now - begin) / 60 if config.plugins.merlinEpgCenter.showBeginRemainTime.value: if (KEEP_OUTDATED_TIME == 0 and (begin + duration) > now) or (KEEP_OUTDATED_TIME != 0 and (begin + duration) > now): if config.plugins.merlinEpgCenter.showDuration.value: remainBeginString = " I " else: remainBeginString = "" if timeValue >= 0: remainBeginString += "+" if fabs(timeValue) >= 120 and fabs(timeValue) < 1440: timeValue /= 60 remainBeginString += "%0dh" % timeValue elif fabs(timeValue) >= 1440: timeValue = (timeValue / 1440) +1 remainBeginString += "%02dd" % timeValue else: if timeValue < 0: remainBeginString += "%03d" % timeValue else: remainBeginString += "%02d" % timeValue else: if config.plugins.merlinEpgCenter.showDuration.value: remainBeginString = " I <->" else: remainBeginString = "<->" else: remainBeginString = "" if config.plugins.merlinEpgCenter.showDuration.value: duraString = "%d" % (duration / 60) if self.mode == MULTI_EPG_NOW: if config.plugins.merlinEpgCenter.listProgressStyle.value == STYLE_MULTI_PIXMAP: part = int(round(percent / 25)) + 1 progressPixmap = eval('self.progressPixmap_' + str(part)) elif config.plugins.merlinEpgCenter.listProgressStyle.value == STYLE_PIXMAP_BAR: progressPixmap = self.progressPixmap else: timeString = "" duraString = "" remainBeginString = "" if remainBeginString.endswith('>'): # KEEP_OUTDATED_TIME outdated = True try: progColor = parseColor("eventNotAvailable").argb() except: progColor = 0x777777 elif config.plugins.merlinEpgCenter.showBeginRemainTime.value and config.plugins.merlinEpgCenter.showColoredEpgTimes.value: outdated = False if remainBeginString.endswith('h'): # begins in... hours progColor = 0x00ef7f1a # brown elif remainBeginString.endswith('d'): # begins in... days progColor = 0x00e31e24 # red elif remainBeginString.startswith(' I +') or remainBeginString.startswith('+'): # already running progColor = 0x0074de0a # green elif remainBeginString.startswith(' I -') or remainBeginString.startswith('-'): # begins in... minutes progColor = 0x00ffed00 # yellow else: # undefined, shouldn't happen progColor = 0x00ffffff # white else: outdated = False progColor = 0x00ffed00 # yellow if outdated: textColor = progColor elif self.epgList != None: textColor = self.epgList.getColorEventAvailable(sRef, begin, duration) else: textColor = None res = [ None ] if config.plugins.merlinEpgCenter.showListNumbers.value: if ((self.mode == SINGLE_EPG and not self.similarShown) or self.mode == UPCOMING) and self.instance.getCurrentIndex() != 0: chNumber = "" else: # check if the service is found in our bouquets (or don't show the channel number if not found) if self.mode == EPGSEARCH_RESULT: if sRef in EpgCenterList.allServicesNameDict: i = 0 while i < len(EpgCenterList.bouquetServices): if sRef in EpgCenterList.bouquetServices[i]: chOffset = EpgCenterList.bouquetIndexRanges[i] chNumber = str(EpgCenterList.bouquetServices[i].index(sRef) + chOffset) break i += 1 else: chNumber = "" else: if sRef in EpgCenterList.bouquetServices[EpgCenterList.currentBouquetIndex]: chOffset = EpgCenterList.bouquetIndexRanges[EpgCenterList.currentBouquetIndex] chNumber = str(EpgCenterList.bouquetServices[EpgCenterList.currentBouquetIndex].index(sRef) + chOffset) else: chNumber = "" if EpgCenterList.lenChannelDigits < 3: width = self.maxWidth * 3 / 100 else: width = self.maxWidth * 4 / 100 res.append((eListboxPythonMultiContent.TYPE_TEXT, offsetLeft, 0, width, self.itemHeight, 1, RT_HALIGN_RIGHT|RT_VALIGN_CENTER, chNumber)) offsetLeft = offsetLeft + width + columnSpace if config.plugins.merlinEpgCenter.showPicons.value: if ((self.mode == SINGLE_EPG and not self.similarShown) or self.mode == UPCOMING) and self.instance.getCurrentIndex() != 0: picon = None else: picon = self.piconLoader.getPicon(sRef) width = self.piconSize.width() if picon: res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetLeft, (self.itemHeight - self.baseHeight) / 2, width, self.itemHeight, picon)) offsetLeft = offsetLeft + width + columnSpace if config.plugins.merlinEpgCenter.showServiceName.value: extraWidth = int(config.plugins.merlinEpgCenter.serviceNameWidth.value) if self.videoMode == MODE_SD: width = self.maxWidth * (12 + extraWidth) / 100 elif self.videoMode == MODE_XD: width = self.maxWidth * (14 + extraWidth) / 100 elif self.videoMode == MODE_HD: width = self.maxWidth * (16 + extraWidth) / 100 if not (((self.mode == SINGLE_EPG and not self.similarShown) or self.mode == UPCOMING) and self.instance.getCurrentIndex() != 0): if sRef in EpgCenterList.allServicesNameDict: serviceName = EpgCenterList.allServicesNameDict[sRef] else: serviceName = ServiceReference(sRef).getServiceName() res.append((eListboxPythonMultiContent.TYPE_TEXT, offsetLeft, 0, width, self.itemHeight, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, serviceName)) offsetLeft = offsetLeft + width + columnSpace if self.mode == MULTI_EPG_NOW and not self.similarShown: extraWidth = int(config.plugins.merlinEpgCenter.adjustFontSize.value) if extraWidth < 0: extraWidth = 0 if self.videoMode == MODE_SD: width = self.maxWidth * (18 + extraWidth) / 100 else: width = self.maxWidth * (14 + extraWidth) / 100 progressHeight = 6 if config.plugins.merlinEpgCenter.listProgressStyle.value < STYLE_SIMPLE_BAR_LIST_OFF: # show progress in lists res.append((eListboxPythonMultiContent.TYPE_TEXT, offsetLeft, border, width, self.halfItemHeight - border + (self.singleLineBorder * 2), 1, RT_HALIGN_CENTER|RT_VALIGN_TOP, timeString)) else: # don't show progress in lists res.append((eListboxPythonMultiContent.TYPE_TEXT, offsetLeft, 0, width, self.itemHeight, 1, RT_HALIGN_CENTER|RT_VALIGN_CENTER, timeString)) if config.plugins.merlinEpgCenter.listProgressStyle.value == STYLE_MULTI_PIXMAP and progressPixmap is not None: if width > self.progressPixmapWidth: progressOffset = int((width - self.progressPixmapWidth) / 2) else: progressOffset = 0 res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetLeft + progressOffset, self.halfItemHeight + (self.halfItemHeight - progressHeight) / 2 + self.singleLineBorder, width, progressHeight, progressPixmap)) elif config.plugins.merlinEpgCenter.listProgressStyle.value == STYLE_SIMPLE_BAR: res.append((eListboxPythonMultiContent.TYPE_PROGRESS, offsetLeft, self.halfItemHeight + (self.halfItemHeight - progressHeight) / 2 + self.singleLineBorder, width, progressHeight, percent, 1, secondLineColor)) elif config.plugins.merlinEpgCenter.listProgressStyle.value == STYLE_PIXMAP_BAR and progressPixmap is not None: if width > self.progressPixmapWidth: progressOffset = int((width - self.progressPixmapWidth) / 2) else: progressOffset = 0 res.append((eListboxPythonMultiContent.TYPE_PROGRESS_PIXMAP, offsetLeft + progressOffset, self.halfItemHeight + (self.halfItemHeight - progressHeight) / 2 + self.singleLineBorder, width, progressHeight, percent, progressPixmap, 0)) elif config.plugins.merlinEpgCenter.listProgressStyle.value == STYLE_PERCENT_TEXT: if self.videoMode == MODE_SD: # we need a bigger font for SD skins font = 2 else: font = 3 res.append((eListboxPythonMultiContent.TYPE_TEXT, offsetLeft, self.halfItemHeight, width, self.halfItemHeight - border, font, RT_HALIGN_CENTER|RT_VALIGN_TOP, str(percent) + "%", secondLineColor)) offsetLeft = offsetLeft + width + columnSpace else: extraWidth = int(config.plugins.merlinEpgCenter.adjustFontSize.value) if extraWidth < 0: extraWidth = 0 if self.videoMode == MODE_SD: width = self.maxWidth * (18 + extraWidth) / 100 else: width = self.maxWidth * (14 + extraWidth) / 100 if self.mode == SINGLE_EPG or self.mode == EPGSEARCH_RESULT or self.similarShown: fd = getFuzzyDay(begin) res.append((eListboxPythonMultiContent.TYPE_TEXT, offsetLeft, border, width, self.halfItemHeight - border, 1, RT_HALIGN_CENTER|RT_VALIGN_TOP, timeString, textColor)) res.append((eListboxPythonMultiContent.TYPE_TEXT, offsetLeft, self.halfItemHeight, width, self.halfItemHeight - border, 2, RT_HALIGN_CENTER|RT_VALIGN_TOP, fd, secondLineColor)) else: res.append((eListboxPythonMultiContent.TYPE_TEXT, offsetLeft, 0, width, self.itemHeight, 1, RT_HALIGN_CENTER|RT_VALIGN_CENTER, timeString, textColor)) offsetLeft = offsetLeft + width + columnSpace if begin != None and duration != None: (timerPixmaps, zapPixmaps, isRunning) = self.getTimerPixmapsForEntry(sRef, eventid, begin, duration) else: timerPixmaps = 0 zapPixmaps = 0 isRunning = 0 idx = self.instance.getCurrentIndex() self.blinkTimer.updateEntry(self.listType, idx, isRunning) if zapPixmaps: if (zapPixmaps & TIMER_TYPE_EID_MATCH) or (zapPixmaps & TIMER_TYPE_COVERS_FULL) or (zapPixmaps & TIMER_TYPE_EID_REPEATED) or (zapPixmaps & TIMER_TYPE_ADD_COVERS_FULL): posY = 2 height = self.itemHeight - 4 if (zapPixmaps & TIMER_TYPE_EID_MATCH): res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.zap_event_pixmap)) elif (zapPixmaps & TIMER_TYPE_COVERS_FULL): res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.zap_pixmap)) elif (zapPixmaps & TIMER_TYPE_EID_REPEATED): res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.zap_repeated_pixmap)) elif (zapPixmaps & TIMER_TYPE_ADD_COVERS_FULL): res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.zap_add_pixmap)) elif (zapPixmaps & TIMER_TYPE_INSIDE_EVENT) or (zapPixmaps & TIMER_TYPE_ADD_INSIDE_EVENT): posY = self.itemHeight / 2 - 6 height = 12 if (zapPixmaps & TIMER_TYPE_INSIDE_EVENT): res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.zap_pixmap)) elif (zapPixmaps & TIMER_TYPE_ADD_INSIDE_EVENT): res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.zap_add_pixmap)) else: if zapPixmaps & TIMER_TYPE_COVERS_END: posY = self.itemHeight / 2 + 2 height = self.itemHeight - posY - 2 res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.zap_pre_pixmap)) elif zapPixmaps & TIMER_TYPE_ADD_COVERS_END: posY = self.itemHeight / 2 + 2 height = self.itemHeight - posY - 2 res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.zap_add_pixmap)) if zapPixmaps & TIMER_TYPE_COVERS_BEGIN: posY = 2 height = self.itemHeight / 2 - 2 res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.zap_post_pixmap)) elif zapPixmaps & TIMER_TYPE_ADD_COVERS_BEGIN: posY = 2 height = self.itemHeight / 2 - 2 res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.zap_add_pixmap)) if zapPixmaps & TIMER_TYPE_ADD: posY = 2 height = self.itemHeight - 4 res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.zap_add_pixmap)) offsetRight -= 10 if timerPixmaps: if (timerPixmaps & TIMER_TYPE_EID_MATCH) or (timerPixmaps & TIMER_TYPE_COVERS_FULL) or (timerPixmaps & TIMER_TYPE_EID_REPEATED) or (timerPixmaps & TIMER_TYPE_ADD_COVERS_FULL): posY = 2 height = self.itemHeight - 4 if (timerPixmaps & TIMER_TYPE_EID_MATCH): if (isRunning & TIMER_TYPE_EID_MATCH) and not self.blinkTimer.getBlinkState(): res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, None)) else: res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.timer_event_pixmap)) elif (timerPixmaps & TIMER_TYPE_COVERS_FULL): if (isRunning & TIMER_TYPE_COVERS_FULL) and not self.blinkTimer.getBlinkState(): res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, None)) else: res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.timer_pixmap)) elif (timerPixmaps & TIMER_TYPE_EID_REPEATED): if (isRunning & TIMER_TYPE_EID_REPEATED) and not self.blinkTimer.getBlinkState(): res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, None)) else: res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.timer_repeated_pixmap)) elif (timerPixmaps & TIMER_TYPE_ADD_COVERS_FULL): res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.timer_add_pixmap)) elif (timerPixmaps & TIMER_TYPE_INSIDE_EVENT) or (timerPixmaps & TIMER_TYPE_ADD_INSIDE_EVENT): posY = self.itemHeight / 2 - 6 height = 12 if (timerPixmaps & TIMER_TYPE_INSIDE_EVENT): if (isRunning & TIMER_TYPE_INSIDE_EVENT) and not self.blinkTimer.getBlinkState(): res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, None)) else: res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.timer_pixmap)) elif (timerPixmaps & TIMER_TYPE_ADD_INSIDE_EVENT): res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.timer_add_pixmap)) else: if timerPixmaps & TIMER_TYPE_COVERS_END: posY = self.itemHeight / 2 + 2 height = self.itemHeight - posY - 2 if (isRunning & TIMER_TYPE_COVERS_END) and not self.blinkTimer.getBlinkState(): res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, None)) else: res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.timer_pre_pixmap)) elif timerPixmaps & TIMER_TYPE_ADD_COVERS_END: posY = self.itemHeight / 2 + 2 height = self.itemHeight - posY - 2 res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.timer_add_pixmap)) if timerPixmaps & TIMER_TYPE_COVERS_BEGIN: posY = 2 height = self.itemHeight / 2 - 2 if (isRunning & TIMER_TYPE_COVERS_BEGIN) and not self.blinkTimer.getBlinkState(): res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, None)) else: res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.timer_post_pixmap)) elif timerPixmaps & TIMER_TYPE_ADD_COVERS_BEGIN: posY = 2 height = self.itemHeight / 2 - 2 res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.timer_add_pixmap)) if timerPixmaps & TIMER_TYPE_ADD: posY = 2 height = self.itemHeight - 4 res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, offsetRight, posY, 8, height, self.timer_add_pixmap)) if config.plugins.merlinEpgCenter.showBeginRemainTime.value and config.plugins.merlinEpgCenter.showDuration.value: width = self.maxWidth * 8 / 100 offsetRight = offsetRight - width res.append((eListboxPythonMultiContent.TYPE_TEXT, offsetRight, 0, width, self.itemHeight, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, remainBeginString, progColor)) elif config.plugins.merlinEpgCenter.showBeginRemainTime.value: width = self.maxWidth * 6 / 100 offsetRight = offsetRight - width res.append((eListboxPythonMultiContent.TYPE_TEXT, offsetRight, 0, width, self.itemHeight, 1, RT_HALIGN_RIGHT|RT_VALIGN_CENTER, remainBeginString, progColor)) if config.plugins.merlinEpgCenter.showDuration.value: width = self.maxWidth * 6 / 100 offsetRight = offsetRight - width elif not config.plugins.merlinEpgCenter.showDuration.value and not config.plugins.merlinEpgCenter.showBeginRemainTime.value: width = self.maxWidth * 1 / 100 offsetRight = offsetRight - width titleWidth = offsetRight - offsetLeft - columnSpace if self.listStyle == STYLE_SINGLE_LINE: res.append((eListboxPythonMultiContent.TYPE_TEXT, offsetLeft, 0, titleWidth, self.itemHeight, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, title, config.plugins.merlinEpgCenter.titleColor.value, config.plugins.merlinEpgCenter.titleColorSelected.value)) elif self.listStyle == STYLE_SHORT_DESCRIPTION: if short and title != short: res.append((eListboxPythonMultiContent.TYPE_TEXT, offsetLeft, border, titleWidth, self.halfItemHeight - border, 1, RT_HALIGN_LEFT|RT_VALIGN_TOP, title, textColor)) res.append((eListboxPythonMultiContent.TYPE_TEXT, offsetLeft, self.halfItemHeight, titleWidth, self.halfItemHeight - border, 2, RT_HALIGN_LEFT|RT_VALIGN_TOP, short, secondLineColor)) else: res.append((eListboxPythonMultiContent.TYPE_TEXT, offsetLeft, 0, titleWidth, self.itemHeight, 1, RT_HALIGN_LEFT|RT_VALIGN_CENTER, title, textColor)) if config.plugins.merlinEpgCenter.showDuration.value: res.append((eListboxPythonMultiContent.TYPE_TEXT, offsetRight, 0, width, self.itemHeight, 1, RT_HALIGN_RIGHT|RT_VALIGN_CENTER, duraString, textColor)) return res GUI_WIDGET = eListbox def selectionChanged(self): for x in self.onSelectionChanged: x() def postWidgetCreate(self, instance): instance.setWrapAround(True) instance.setContent(self.l) instance.selectionChanged.get().append(self.selectionChanged) def preWidgetRemove(self, instance): instance.setContent(None) instance.selectionChanged.get().remove(self.selectionChanged) config.plugins.merlinEpgCenter.listItemHeight.removeNotifier(self.changeHeight) config.plugins.merlinEpgCenter.adjustFontSize.removeNotifier(self.setFontSizes) self.blinkTimer.callbacks.remove(self.invalidateList) def moveToIndex(self, index): self.instance.moveSelectionTo(index) def moveUp(self): self.instance.moveSelection(self.instance.moveUp) def moveDown(self): self.instance.moveSelection(self.instance.moveDown) def pageUp(self): if self.instance is not None: self.instance.moveSelection(self.instance.pageUp) def pageDown(self): if self.instance is not None: self.instance.moveSelection(self.instance.pageDown) def getCurrent(self): return self.l.getCurrentSelection() def invalidate(self, entry): # when the entry to invalidate does not exist, just ignore the request. # this eases up conditional setup screens a lot. if entry in self.list: self.l.invalidateEntry(self.list.index(entry)) def invalidateList(self): self.l.invalidate() def setList(self, l): self.list = l self.l.setList(self.list) def queryEPG(self, servicelist): if self.epgcache is not None: return self.epgcache.lookupEvent(servicelist) return [ ] def fillMultiEPG(self, bouquet, bouquetIndex, mode, stime=-1): EpgCenterList.currentBouquetIndex = bouquetIndex # 1. if oldmode is MULTI_EPG_NOW and new mode is MULTI_EPG_NEXT --> use old list for querying EPG (speed up! :-) ) # 2. otherwise build servicelist from bouquet, and # a) if MULTI_EPG_NOW/MULTI_EPG_PRIMETIME --> query epg # b) if MULTI_EPG_NEXT --> build query-list with servicelist for epg oldmode = self.mode self.mode = mode self.similarShown = False if ((mode == MULTI_EPG_NOW or mode == MULTI_EPG_PRIMETIME) or (oldmode != MULTI_EPG_NOW and mode == MULTI_EPG_NEXT)): servicelist = EpgCenterList.getServiceList(bouquet, stime) returnTuples = '0IRBDTSEX' if mode == MULTI_EPG_NOW or mode == MULTI_EPG_PRIMETIME: servicelist.insert(0, returnTuples) else: if oldmode != MULTI_EPG_NOW: servicelist.insert(0, returnTuples) tmpList = self.queryEPG(servicelist) else: tmpList = self.list servicelist = [ x[3] and (x[2], 1, x[3]) or (x[2], 1, 0) for x in tmpList ] # build servicelist with "event after given start_time" and set the start time servicelist.insert(0, returnTuples) if self.listStyle == STYLE_SINGLE_LINE: self.changeHeight() self.list = self.queryEPG(servicelist) self.l.setList(self.list) def fillSingleEPG(self, bouquet, bouquetIndex, mode, sRef, showOutdated): self.mode = mode EpgCenterList.currentBouquetIndex = bouquetIndex EpgCenterList.getServiceList(bouquet) self.similarShown = False if sRef: if showOutdated: now = time() queryString = [ '0IRBDTSE', (sRef, 0, now - KEEP_OUTDATED_TIME * 60, KEEP_OUTDATED_TIME) ] else: queryString = [ '0IRBDTSE', (sRef, 0, -1, -1) ] self.list = self.queryEPG(queryString) if self.listStyle == STYLE_SINGLE_LINE: self.changeHeight() if showOutdated: self.list.sort(key = lambda x: x[3], reverse = True) # sort by time self.l.setList(self.list) def fillSimilar(self, sRef, eventId): if eventId is None: return self.similarShown = True self.list = self.epgcache.search(('0IRBDTSE', 1024, eEPGCache.SIMILAR_BROADCASTINGS_SEARCH, sRef, eventId)) if self.list is not None: if config.plugins.merlinEpgCenter.limitSearchToBouquetServices.value: for item in self.list[:]: if not item[2] in EpgCenterList.allServicesNameDict: self.list.remove(item) if self.listStyle == STYLE_SINGLE_LINE: self.changeHeight() self.list.sort(key = lambda x: x[3]) # sort by time self.l.setList(self.list) def fillEpgSearch(self, searchString, mode): self.mode = mode self.similarShown = False if searchString == None: self.list = [] else: searchString = searchString.decode('utf-8').encode("iso-8859-1","replace") self.list = self.epgcache.search(('0IRBDTSE', 1024, eEPGCache.PARTIAL_TITLE_SEARCH, searchString, eEPGCache.NO_CASE_CHECK)) or [] if config.plugins.merlinEpgCenter.limitSearchToBouquetServices.value: for item in self.list[:]: if not item[2] in EpgCenterList.allServicesNameDict: self.list.remove(item) self.list.sort(key = lambda x: x[3]) # sort by time if self.listStyle == STYLE_SINGLE_LINE: self.changeHeight() self.l.setList(self.list) @staticmethod def getServiceList(bouquet, stime=-1, sRefOnly = False): services = [ ] servicelist = eServiceCenter.getInstance().list(bouquet) if not servicelist is None: while True: service = servicelist.getNext() if not service.valid(): # check if end of list break if service.flags & (eServiceReference.isDirectory | eServiceReference.isMarker): # ignore non playable services continue # alternative service? if service.flags & (eServiceReference.isGroup): altRoot = eServiceReference(service.toCompareString()) altList = EpgCenterList.eServiceCenterInstance.list(altRoot) if altList: while True: nextService = altList.getNext() if not nextService.valid(): break service = nextService break if sRefOnly: services.append(service.toCompareString()) else: services.append((service.toCompareString(), 0, stime)) return services # get a list of all services in all bouquets @staticmethod def getAllServices(): allServices = {} index = 1 EpgCenterList.lenChannelDigits = 0 totalServices = 0 # the number of services in all bouquets for bouquetEntry in EpgCenterList.bouquetList: servicelist = eServiceCenter.getInstance().list(bouquetEntry[1]) if not servicelist is None: numServices = 0 while True: service = servicelist.getNext() if not service.valid(): # check if end of list break if service.flags & (eServiceReference.isDirectory | eServiceReference.isMarker): # ignore non playable services continue info = EpgCenterList.eServiceCenterInstance.info(service) serviceName = info.getName(service) or ServiceReference(service).getServiceName() or "" allServices[service.toCompareString()] = serviceName numServices += 1 indexEntry = index index += numServices totalServices += numServices EpgCenterList.bouquetIndexRanges.append(indexEntry) EpgCenterList.lenChannelDigits = len(str(totalServices)) return allServices @staticmethod def updateBouquetServices(): EpgCenterList.bouquetIndexRanges = [] EpgCenterList.allServicesNameDict = EpgCenterList.getAllServices() EpgCenterList.bouquetServices = [] for bouquet in EpgCenterList.bouquetList: EpgCenterList.bouquetServices.append(EpgCenterList.getServiceList(bouquet[1], sRefOnly = True)) def selectionEnabled(self, enabled): if self.instance is not None: self.instance.setSelectionEnable(enabled) def getTimerPixmapsForEntry(self, sRef, eventId, begin, duration): timerPixmaps = 0 zapPixmaps = 0 isRunning = 0 for timer in self.recordTimer.timer_list: if timer.service_ref.ref.toString() == sRef: end = begin + duration if timer.begin > begin and timer.end < end: # the timer is inside the events bounds if timer.justplay: zapPixmaps |= TIMER_TYPE_INSIDE_EVENT else: timerPixmaps |= TIMER_TYPE_INSIDE_EVENT if timer.isRunning(): isRunning |= TIMER_TYPE_INSIDE_EVENT elif end >= timer.begin and begin <= timer.end: # this event touches the timer if eventId == timer.eit: # exact event match if timer.repeated: if timer.justplay: zapPixmaps |= TIMER_TYPE_EID_REPEATED else: timerPixmaps |= TIMER_TYPE_EID_REPEATED if timer.isRunning(): isRunning |= TIMER_TYPE_EID_REPEATED else: if timer.justplay: zapPixmaps |= TIMER_TYPE_EID_MATCH else: timerPixmaps |= TIMER_TYPE_EID_MATCH if timer.isRunning(): isRunning |= TIMER_TYPE_EID_MATCH elif begin < timer.begin and end > timer.begin: # this event overlaps the end of the timer if timer.justplay: zapPixmaps |= TIMER_TYPE_COVERS_END else: timerPixmaps |= TIMER_TYPE_COVERS_END if timer.isRunning(): isRunning |= TIMER_TYPE_COVERS_END elif end > timer.end and begin < timer.end: # this event overlaps the begin of the timer if timer.justplay: zapPixmaps |= TIMER_TYPE_COVERS_BEGIN else: timerPixmaps |= TIMER_TYPE_COVERS_BEGIN if timer.isRunning(): isRunning |= TIMER_TYPE_COVERS_BEGIN elif end > timer.begin and begin < timer.end: # this event fully overlaps the timer but itsn't nor the timer event if timer.justplay: zapPixmaps |= TIMER_TYPE_COVERS_FULL else: timerPixmaps |= TIMER_TYPE_COVERS_FULL if timer.isRunning(): isRunning |= TIMER_TYPE_COVERS_FULL elif timerPixmaps == 0 and zapPixmaps == 0 and self.recordTimer.isInTimer(eventId, begin, duration, sRef): # timer repetition # TODO do we need to care about local times? timerBegin = datetime.fromtimestamp(timer.begin).time() timerEnd = datetime.fromtimestamp(timer.end).time() netTimerBegin = datetime.fromtimestamp(int(timer.begin) + 60 * config.recording.margin_before.getValue()).time() netTimerEnd = datetime.fromtimestamp(int(timer.end) - 60 * config.recording.margin_after.getValue()).time() eventBegin = datetime.fromtimestamp(begin).time() eventEnd = datetime.fromtimestamp(end).time() if netTimerBegin == eventBegin and netTimerEnd == eventEnd: # the main timer entry if timer.justplay: zapPixmaps |= TIMER_TYPE_ADD else: timerPixmaps |= TIMER_TYPE_ADD elif netTimerBegin >= eventBegin and netTimerEnd <= eventEnd: # the timer is inside the events bounds if timer.justplay: zapPixmaps |= TIMER_TYPE_ADD_INSIDE_EVENT else: timerPixmaps |= TIMER_TYPE_ADD_INSIDE_EVENT elif eventBegin < timerBegin and eventEnd > timerBegin: # this event overlaps the end of the timer if timer.justplay: zapPixmaps |= TIMER_TYPE_ADD_COVERS_END else: timerPixmaps |= TIMER_TYPE_ADD_COVERS_END elif eventEnd > timerEnd and eventBegin < timerEnd: # this event overlaps the begin of the timer if timer.justplay: zapPixmaps |= TIMER_TYPE_ADD_COVERS_BEGIN else: timerPixmaps |= TIMER_TYPE_ADD_COVERS_BEGIN elif eventEnd > timerBegin and eventBegin < timerEnd: # this event fully overlaps the timer but itsn't nor the timer event if timer.justplay: zapPixmaps |= TIMER_TYPE_ADD_COVERS_FULL else: timerPixmaps |= TIMER_TYPE_ADD_COVERS_FULL return timerPixmaps, zapPixmaps, isRunning
class MovieList(GUIComponent): SORT_ALPHANUMERIC = SORT_ALPHA_DATE_NEWEST_FIRST = 1 SORT_RECORDED = SORT_DATE_NEWEST_FIRST_ALPHA = 2 SHUFFLE = 3 SORT_ALPHANUMERIC_REVERSE = SORT_ALPHAREV_DATE_OLDEST_FIRST = 4 SORT_RECORDED_REVERSE = SORT_DATE_OLDEST_FIRST_ALPHAREV = 5 SORT_ALPHANUMERIC_FLAT = SORT_ALPHA_DATE_NEWEST_FIRST_FLAT = 6 SORT_ALPHANUMERIC_FLAT_REVERSE = SORT_ALPHAREV_DATE_OLDEST_FIRST_FLAT = 7 SORT_GROUPWISE = 8 SORT_ALPHA_DATE_OLDEST_FIRST = 9 SORT_ALPHAREV_DATE_NEWEST_FIRST = 10 SORT_DURATION_ALPHA = 11 SORT_DURATIONREV_ALPHA = 12 SORT_SIZE_ALPHA = 13 SORT_SIZEREV_ALPHA = 14 HIDE_DESCRIPTION = 1 SHOW_DESCRIPTION = 2 COL_NAME = 1 COL_BEGIN = 2 COL_LENGTH = 3 COL_SIZE = 4 staticCols = frozenset([COL_NAME, COL_BEGIN]) sortCols = { SORT_DURATION_ALPHA: staticCols | frozenset([COL_LENGTH]), SORT_DURATIONREV_ALPHA: staticCols | frozenset([COL_LENGTH]), SORT_SIZE_ALPHA: staticCols | frozenset([COL_SIZE]), SORT_SIZEREV_ALPHA: staticCols | frozenset([COL_SIZE]), } dirNameExclusions = [ '.AppleDouble', '.AppleDesktop', '.AppleDB', 'Network Trash Folder', 'Temporary Items', '.TemporaryItems' ] # GML:1 # So MovieSelection.selectSortby() can find out whether we are # in a Trash folder and, if so, what the last sort was # The numbering starts after SORT_* values above. # in MovieSelection.py (that has no SORT_GROUPWISE) # TRASHSORT_SHOWRECORD = 15 TRASHSORT_SHOWDELETE = 16 UsingTrashSort = False InTrashFolder = False def __init__(self, root, sort_type=None, descr_state=None): GUIComponent.__init__(self) self.list = [] self.descr_state = descr_state or self.HIDE_DESCRIPTION self.sort_type = sort_type or self.SORT_GROUPWISE self.firstFileEntry = 0 self.parentDirectory = 0 self.numUserDirs = 0 # does not include parent or Trashcan self.numUserFiles = 0 self.fontName, self.fontSize, height, width = skin.fonts.get("MovieSelectionFont", ("Regular", 20, 25, 18)) self.listHeight = None self.listWidth = None # pbarShift, trashShift, dirShift, markShift, dateWidth, lenWidth # and sizeWidth are properties that return their # calculated size if set to None self.pbarShift = None # Defaults to being calculated from bar height self.pbarHeight = 16 self.pbarLargeWidth = 48 self.pbarColour = 0x206333 self.pbarColourSeen = 0xffc71d self.pbarColourRec = 0xff001d self.pbarColourSel = 0x20a333 self.pbarColourSeenSel = 0xffc71d self.pbarColourRecSel = 0xff001d # Unlike pbarShift and trashShift, etc below, # partIconeShift is an ordinary attribute, because # its "None" value is calculated per row in the list self.partIconeShift = None # Defaults to being calculated from icon height self.spaceRight = 2 self.spaceIconeText = 2 self.listPos = 50 self.markWidth = 16 self.iconsWidth = 22 self.trashShift = None # Defaults to being calculated from trash icon height self.dirShift = None # Defaults to being calculated from directory icon height self.markShift = None # Defaults to being calculated from selected icon height self.dateWidth = None # Defaults to being calculated from font size self.dateWidthScale = 9.0 # Over-ridden by self.dateWidth if set self.lenWidth = None # Defaults to being calculated from font size self.lenWidthScale = 4.0 # Over-ridden by self.lenWidth if set self.sizeWidth = None # Defaults to being calculated from font size self.sizeWidthScale = 5.0 # Over-ridden by self.sizeWidth if set self.reloadDelayTimer = None self.l = eListboxPythonMultiContent() self.tags = set() self.root = None self._playInBackground = None self._playInForeground = None self._char = '' self.markList = [] if root is not None: self.reload(root) self.l.setBuildFunc(self.buildMovieListEntry) self.onSelectionChanged = [] self.iconPart = [] for part in range(5): self.iconPart.append(LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, "icons/part_%d_4.png" % part))) self.iconMovieRec = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, "icons/part_new.png")) self.iconMoviePlay = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, "icons/movie_play.png")) self.iconMoviePlayRec = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, "icons/movie_play_rec.png")) self.iconUnwatched = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, "icons/part_unwatched.png")) self.iconFolder = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, "icons/folder.png")) self.iconTrash = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, "icons/trashcan.png")) self.runningTimers = {} self.updateRecordings() self.updatePlayPosCache() self.iconMarked = [LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, "icons/mark_off.png")), LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, "icons/mark_on.png"))] @property def dateWidth(self): if self._dateWidth is None: return int(((self.fontSize - 3) + config.movielist.fontsize.value) * self.dateWidthScale) else: return self._dateWidth @dateWidth.setter def dateWidth(self, val): self._dateWidth = val @property def lenWidth(self): if self._lenWidth is None: return int(((self.fontSize - 3) + config.movielist.fontsize.value) * self.lenWidthScale) else: return self._lenWidth @lenWidth.setter def lenWidth(self, val): self._lenWidth = val @property def sizeWidth(self): if self._sizeWidth is None: return int(((self.fontSize - 3) + config.movielist.fontsize.value) * self.sizeWidthScale) else: return self._sizeWidth @sizeWidth.setter def sizeWidth(self, val): self._sizeWidth = val @property def trashShift(self): if self._trashShift is None: return max(0, int((self.itemHeight - self.iconTrash.size().height() + 1.0) / 2)) else: return self._trashShift @trashShift.setter def trashShift(self, val): self._trashShift = val @property def dirShift(self): if self._dirShift is None: return max(0, int((self.itemHeight - self.iconFolder.size().height() + 1.0) / 2)) else: return self._dirShift @dirShift.setter def dirShift(self, val): self._dirShift = val @property def markShift(self): if self._markShift is None: # assume on & off are the same size markHeight = self.iconMarked[0].size().height() # prefer to chop off the top, not the bottom if markHeight >= self.itemHeight: return self.itemHeight - markHeight return max(0, int((self.itemHeight - markHeight + 1.0) / 2)) else: return self._markShift @markShift.setter def markShift(self, val): self._markShift = val @property def pbarShift(self): if self._pbarShift is None: return max(0, int((self.itemHeight - self.pbarHeight) / 2)) else: return self._pbarShift @pbarShift.setter def pbarShift(self, val): self._pbarShift = val def get_playInBackground(self): return self._playInBackground def set_playInBackground(self, value): if self._playInBackground is not value: index = self.findService(self._playInBackground) if index is not None: self.invalidateItem(index) index = self.findService(value) if index is not None: self.invalidateItem(index) self._playInBackground = value playInBackground = property(get_playInBackground, set_playInBackground) def get_playInForeground(self): return self._playInForeground def set_playInForeground(self, value): self._playInForeground = value playInForeground = property(get_playInForeground, set_playInForeground) def updatePlayPosCache(self): from Screens.InfoBarGenerics import updateresumePointCache updateresumePointCache() def updateRecordings(self, timer=None): if timer is not None: if timer.justplay: return result = {} for timer in NavigationInstance.instance.RecordTimer.timer_list: if timer.isRunning() and not timer.justplay and not timer.failed: result[os.path.basename(timer.Filename) + '.ts'] = timer if self.runningTimers == result: return self.runningTimers = result if timer is not None: if self.reloadDelayTimer is not None: self.reloadDelayTimer.stop() self.reloadDelayTimer = eTimer() self.reloadDelayTimer.callback.append(self.reload) self.reloadDelayTimer.start(5000, 1) def connectSelChanged(self, fnc): if fnc not in self.onSelectionChanged: self.onSelectionChanged.append(fnc) def disconnectSelChanged(self, fnc): if fnc in self.onSelectionChanged: self.onSelectionChanged.remove(fnc) def selectionChanged(self): for x in self.onSelectionChanged: x() def setDescriptionState(self, val): self.descr_state = val def setSortType(self, type): self.sort_type = type def applySkin(self, desktop, parent): def warningWrongSkinParameter(string): print "[MovieList] wrong '%s' skin parameters" % string def font(value): font = skin.parseFont(value, ((1, 1), (1, 1))) self.fontName = font.family self.fontSize = font.pointSize def pbarShift(value): self.pbarShift = int(value) def pbarHeight(value): self.pbarHeight = int(value) def pbarLargeWidth(value): self.pbarLargeWidth = int(value) def pbarColour(value): self.pbarColour = skin.parseColor(value).argb() def pbarColourSeen(value): self.pbarColourSeen = skin.parseColor(value).argb() def pbarColourRec(value): self.pbarColourRec = skin.parseColor(value).argb() def pbarColourSel(value): self.pbarColourSel = skin.parseColor(value).argb() def pbarColourSeenSel(value): self.pbarColourSeenSel = skin.parseColor(value).argb() def pbarColourRecSel(value): self.pbarColourRecSel = skin.parseColor(value).argb() def partIconeShift(value): self.partIconeShift = int(value) def spaceIconeText(value): self.spaceIconeText = int(value) def listPos(value): self.listPos = int(value) def markWidth(value): self.markWidth = int(value) def iconsWidth(value): self.iconsWidth = int(value) def trashShift(value): self.trashShift = int(value) def dirShift(value): self.dirShift = int(value) def markShift(value): self.markShift = int(value) def spaceRight(value): self.spaceRight = int(value) def dateWidth(value): self.dateWidth = int(value) def dateWidthScale(value): self.dateWidthScale = float(value) def lenWidth(value): self.lenWidth = int(value) def lenWidthScale(value): self.lenWidthScale = float(value) def sizeWidth(value): self.sizeWidth = int(value) def sizeWidthScale(value): self.sizeWidthScale = float(value) for (attrib, value) in self.skinAttributes[:]: try: locals().get(attrib)(value) self.skinAttributes.remove((attrib, value)) except: pass rc = GUIComponent.applySkin(self, desktop, parent) self.listHeight = self.instance.size().height() self.listWidth = self.instance.size().width() self.setFontsize() self.setItemsPerPage() return rc def setItemsPerPage(self): if self.listHeight > 0: itemHeight = self.listHeight / config.movielist.itemsperpage.value else: itemHeight = 25 # some default (270/5) self.itemHeight = itemHeight self.l.setItemHeight(itemHeight) self.l.setSelectionClip(eRect(self.listPos, 0, self.listWidth - self.listPos, itemHeight), False) self.instance.resize(eSize(self.listWidth, self.listHeight / itemHeight * itemHeight)) def setFontsize(self): self.l.setFont(0, gFont(self.fontName, self.fontSize + config.movielist.fontsize.value)) self.l.setFont(1, gFont(self.fontName, (self.fontSize - 3) + config.movielist.fontsize.value)) def invalidateItem(self, index): x = self.list[index] self.list[index] = (x[0], x[1], x[2], None) self.l.invalidateEntry(index) def invalidateCurrentItem(self): self.invalidateItem(self.getCurrentIndex()) def userItemCount(self): return (self.numUserDirs, self.numUserFiles) def showCol(self, conf, col): return conf.value == "yes" or conf.value == "auto" and col in self.sortCols.get(self.sort_type, self.staticCols) def buildMovieListEntry(self, serviceref, info, begin, data): switch = config.usage.show_icons_in_movielist.value width = self.l.getItemSize().width() dateWidth = self.dateWidth if config.usage.time.wide.value: dateWidth = int(dateWidth * 1.15) if not config.movielist.use_fuzzy_dates.value: dateWidth += 35 showLen = self.showCol(config.movielist.showlengths, self.COL_LENGTH) lenWidth = self.lenWidth if showLen else 0 showSize = self.showCol(config.movielist.showsizes, self.COL_SIZE) sizeWidth = self.sizeWidth if showSize else 0 markSize = self.markWidth iconSize = self.iconsWidth space = self.spaceIconeText r = self.spaceRight ih = self.itemHeight pathName = serviceref.getPath() res = [None] res.append(MultiContentEntryPixmapAlphaBlend(pos=(self.listPos - markSize - space, self.markShift), size=(markSize, self.iconMarked[0].size().height()), png=self.iconMarked[self.getCurrent() in self.markList])) iconPos = self.listPos textPos = iconPos + iconSize + space if serviceref.flags & eServiceReference.mustDescent: # Directory # Name is full path name if info is None: # Special case: "parent" txt = ".." else: txt = os.path.basename(os.path.normpath(pathName)) if txt == ".Trash": res.append(MultiContentEntryPixmapAlphaBlend(pos=(iconPos, self.trashShift), size=(iconSize, self.iconTrash.size().height()), png=self.iconTrash)) res.append(MultiContentEntryText(pos=(textPos, 0), size=(width - textPos - dateWidth - r, ih), font=0, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER, text = _("Trash"))) res.append(MultiContentEntryText(pos=(width - dateWidth - r, 0), size=(dateWidth, ih), font=1, flags=RT_HALIGN_RIGHT | RT_VALIGN_CENTER, text=_("Trash"))) return res res.append(MultiContentEntryPixmapAlphaBlend(pos=(iconPos, self.dirShift), size=(iconSize, iconSize), png=self.iconFolder)) res.append(MultiContentEntryText(pos=(textPos, 0), size=(width - textPos - dateWidth - r, ih), font=0, flags = RT_HALIGN_LEFT | RT_VALIGN_CENTER, text=txt)) res.append(MultiContentEntryText(pos=(width - dateWidth - r, 0), size=(dateWidth, ih), font=1, flags=RT_HALIGN_RIGHT | RT_VALIGN_CENTER, text=_("Directory"))) return res if data == -1 or data is None: data = MovieListData() cur_idx = self.l.getCurrentSelectionIndex() x = self.list[cur_idx] # x = ref,info,begin,... data.len = info.getLength(serviceref) if showSize: data.size = info.getFileSize(serviceref) self.list[cur_idx] = (x[0], x[1], x[2], data) # update entry in list... so next time we don't need to recalc data.txt = info.getName(serviceref) if config.movielist.hide_extensions.value: fileName, fileExtension = os.path.splitext(data.txt) if fileExtension in KNOWN_EXTENSIONS: data.txt = fileName data.icon = None data.part = None if os.path.basename(pathName) in self.runningTimers: if switch == 'i': if (self.playInBackground or self.playInForeground) and serviceref == (self.playInBackground or self.playInForeground): data.icon = self.iconMoviePlayRec else: data.icon = self.iconMovieRec elif switch in ('p', 's'): data.part = 100 if (self.playInBackground or self.playInForeground) and serviceref == (self.playInBackground or self.playInForeground): data.partcol = self.pbarColourSeen data.partcolsel = self.pbarColourSeenSel else: data.partcol = self.pbarColourRec data.partcolsel = self.pbarColourRecSel elif (self.playInBackground or self.playInForeground) and serviceref == (self.playInBackground or self.playInForeground): data.icon = self.iconMoviePlay else: data.part = moviePlayState(pathName + '.cuts', serviceref, data.len * 90000) if switch == 'i': if data.part is not None and data.part >= 0: data.icon = self.iconPart[data.part // 25] else: if config.usage.movielist_unseen.value: data.icon = self.iconUnwatched elif switch in ('p', 's'): if data.part is not None and data.part > 0: data.partcol = self.pbarColourSeen data.partcolsel = self.pbarColourSeenSel else: if config.usage.movielist_unseen.value: data.part = 100 data.partcol = self.pbarColour data.partcolsel = self.pbarColourSel if showLen: len = data.len len = "%d:%02d" % (len / 60, len % 60) if len > 0 else "" if showSize: size = _("%s %sB") % UnitScaler()(data.size) if data.size > 0 else "" if data: if switch == 'i' and hasattr(data, 'icon') and data.icon is not None: if self.partIconeShift is None: partIconeShift = max(0, int((ih - data.icon.size().height()) / 2)) else: partIconeShift = self.partIconeShift pos = (iconPos, partIconeShift) res.append(MultiContentEntryPixmapAlphaBlend(pos=pos, size=(iconSize, data.icon.size().height()), png=data.icon)) elif switch in ('p', 's'): if switch == 'p': iconSize = self.pbarLargeWidth textPos = iconPos + iconSize + space if hasattr(data, 'part') and data.part > 0: res.append(MultiContentEntryProgress(pos=(iconPos, self.pbarShift), size=(iconSize, self.pbarHeight), percent=data.part, borderWidth=2, foreColor=data.partcol, foreColorSelected=data.partcolsel, backColor=None, backColorSelected=None)) elif hasattr(data, 'icon') and data.icon is not None: res.append(MultiContentEntryPixmapAlphaBlend(pos=(iconPos, self.pbarShift), size=(iconSize, self.pbarHeight), png=data.icon)) begin_string = "" if begin > 0: if config.movielist.use_fuzzy_dates.value: begin_string = ' '.join(FuzzyTime(begin, inPast = True)) else: begin_string = strftime("%s %s" % (config.usage.date.daylong.value, config.usage.time.short.value), localtime(begin)) textItems = [] xPos = width if showSize: xPos -= sizeWidth + r textItems.insert(0, MultiContentEntryText(pos=(xPos, 0), size=(sizeWidth, ih), font=1, flags=RT_HALIGN_RIGHT | RT_VALIGN_CENTER, text=size)) if showLen: xPos -= lenWidth + r textItems.insert(0, MultiContentEntryText(pos=(xPos, 0), size=(lenWidth, ih), font=1, flags=RT_HALIGN_RIGHT | RT_VALIGN_CENTER, text=len)) xPos -= dateWidth + r textItems.insert(0, MultiContentEntryText(pos=(xPos, 0), size=(dateWidth, ih), font=1, flags=RT_HALIGN_RIGHT | RT_VALIGN_CENTER, text=begin_string)) textItems.insert(0, MultiContentEntryText(pos=(textPos, 0), size=(xPos - textPos, ih), font=0, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER, text=data.txt)) res += textItems return res def moveToFirstMovie(self): if self.firstFileEntry < len(self.list): self.instance.moveSelectionTo(self.firstFileEntry) else: # there are no movies, just directories... self.moveToFirst() def moveToParentDirectory(self): if self.parentDirectory < len(self.list): self.instance.moveSelectionTo(self.parentDirectory) else: self.moveToFirst() def moveToLast(self): if self.list: self.instance.moveSelectionTo(len(self.list) - 1) def moveToFirst(self): if self.list: self.instance.moveSelectionTo(0) def moveToIndex(self, index): self.instance.moveSelectionTo(index) def getCurrentIndex(self): return self.instance.getCurrentIndex() def getCurrentEvent(self): l = self.l.getCurrentSelection() return l and l[0] and l[1] and l[1].getEvent(l[0]) def getCurrent(self): l = self.l.getCurrentSelection() return l and l[0] def getItem(self, index): if self.list: if len(self.list) > index: return self.list[index] and self.list[index][0] GUI_WIDGET = eListbox def postWidgetCreate(self, instance): instance.setContent(self.l) instance.selectionChanged.get().append(self.selectionChanged) self.setFontsize() def preWidgetRemove(self, instance): instance.setContent(None) instance.selectionChanged.get().remove(self.selectionChanged) def reload(self, root=None, filter_tags=None): if self.reloadDelayTimer is not None: self.reloadDelayTimer.stop() self.reloadDelayTimer = None if root is not None: self.load(root, filter_tags) else: self.load(self.root, filter_tags) self.refreshDisplay() def refreshDisplay(self): self.l.setList(self.list) def removeService(self, service): index = self.findService(service) if index is not None: (serviceref, info, _, _) = self.list[index] pathName = serviceref.getPath() if serviceref.flags & eServiceReference.mustDescent: name = os.path.basename(os.path.normpath(pathName)) if info is not None and name != ".Trash" and self.numUserDirs > 0: self.numUserDirs -= 1 elif self.numUserFiles > 0: self.numUserFiles -= 1 del self.list[index] try: self.markList.remove(serviceref) except: pass self.refreshDisplay() def findService(self, service): if service is None: return None for index, l in enumerate(self.list): if l[0] == service: return index return None def __len__(self): return len(self.list) def __getitem__(self, index): return self.list[index] def __iter__(self): return self.list.__iter__() def load(self, root, filter_tags): # this lists our root service, then building a # nice list self.list = [] serviceHandler = eServiceCenter.getInstance() numberOfDirs = 0 self.numUserDirs = 0 # does not include parent or Trashcan self.numUserFiles = 0 reflist = root and serviceHandler.list(root) if reflist is None: print "[MovieList] listing of movies failed" return realtags = set() autotags = {} rootPath = os.path.normpath(root.getPath()) parent = None # Don't navigate above the "root" if len(rootPath) > 1 and (os.path.realpath(rootPath) != os.path.realpath(config.movielist.root.value)): parent = os.path.dirname(rootPath) # enigma wants an extra '/' appended if not parent.endswith('/'): parent += '/' ref = eServiceReference(eServiceReference.idFile, eServiceReference.flagDirectory, eServiceReferenceFS.directory) ref.setPath(parent) self.list.append((ref, None, 0, -1)) numberOfDirs += 1 # GML:1 if config.usage.movielist_trashcan.value: here = os.path.realpath(rootPath) MovieList.InTrashFolder = here.startswith(getTrashFolder(here)) else: MovieList.InTrashFolder = False MovieList.UsingTrashSort = False if MovieList.InTrashFolder: if (config.usage.trashsort_deltime.value == "show record time"): MovieList.UsingTrashSort = MovieList.TRASHSORT_SHOWRECORD elif (config.usage.trashsort_deltime.value == "show delete time"): MovieList.UsingTrashSort = MovieList.TRASHSORT_SHOWDELETE while 1: serviceref = reflist.getNext() if not serviceref.valid(): break if config.ParentalControl.servicepinactive.value and config.ParentalControl.storeservicepin.value != "never": from Components.ParentalControl import parentalControl if not parentalControl.sessionPinCached and parentalControl.isProtected(serviceref): continue info = serviceHandler.info(serviceref) if info is None: info = justStubInfo begin = info.getInfo(serviceref, iServiceInformation.sTimeCreate) # GML:1 begin2 = 0 if MovieList.UsingTrashSort: f_path = serviceref.getPath() if os.path.exists(f_path): # Override with deltime for sorting if MovieList.UsingTrashSort == MovieList.TRASHSORT_SHOWRECORD: begin2 = begin # Save for later re-instatement begin = os.stat(f_path).st_ctime if serviceref.flags & eServiceReference.mustDescent: dirname = info.getName(serviceref) normdirname = os.path.normpath(dirname) normname = os.path.basename(normdirname) if normname not in MovieList.dirNameExclusions and normdirname not in defaultInhibitDirs: self.list.insert(0, (serviceref, info, begin, -1)) numberOfDirs += 1 if normname != ".Trash": self.numUserDirs += 1 continue # convert space-separated list of tags into a set this_tags = info.getInfoString(serviceref, iServiceInformation.sTags).split(' ') name = info.getName(serviceref) # OSX put a lot of stupid files ._* everywhere... we need to skip them if name[:2] == "._": continue if this_tags == ['']: # No tags? Auto tag! this_tags = name.replace(',', ' ').replace('.', ' ').replace('_', ' ').replace(':', ' ').split() # For auto tags, we are keeping a (tag, movies) dictionary. # It will be used later to check if movies have a complete sentence in common. for tag in this_tags: if tag in autotags: autotags[tag].append(name) else: autotags[tag] = [name] else: realtags.update(this_tags) # filter_tags is either None (which means no filter at all), or # a set. In this case, all elements of filter_tags must be present, # otherwise the entry will be dropped. if filter_tags is not None: this_tags_fullname = [" ".join(this_tags)] this_tags_fullname = set(this_tags_fullname) this_tags = set(this_tags) if not this_tags.issuperset(filter_tags) and not this_tags_fullname.issuperset(filter_tags): # print "[MovieList] Skipping", name, "tags=", this_tags, " filter=", filter_tags continue # GML:1 if begin2 != 0: self.list.append((serviceref, info, begin, -1, begin2)) else: self.list.append((serviceref, info, begin, -1)) self.numUserFiles += 1 self.parentDirectory = 0 # GML:1 if MovieList.UsingTrashSort: # Same as SORT_RECORDED (SORT_DATE_NEWEST_FIRST_ALPHA), but must come first... self.list = sorted(self.list[:numberOfDirs], key=self.buildBeginTimeSortKey) + sorted(self.list[numberOfDirs:], key=self.buildBeginTimeSortKey) # Having sorted on deletion times, re-instate any record times for display. # self.list is a list of tuples, so we can't just assign to elements... # if config.usage.trashsort_deltime.value == "show record time": for i in range(len(self.list)): if len(self.list[i]) == 5: x = self.list[i] self.list[i] = (x[0], x[1], x[4], x[3]) elif self.sort_type == MovieList.SORT_ALPHA_DATE_NEWEST_FIRST: self.list.sort(key=self.buildAlphaNumericSortKey) elif self.sort_type == MovieList.SORT_ALPHAREV_DATE_OLDEST_FIRST: self.list = sorted(self.list[:numberOfDirs], key=self.buildAlphaNumericSortKey, reverse=True) \ + sorted(self.list[numberOfDirs:], key=self.buildAlphaNumericSortKey, reverse=True) elif self.sort_type == MovieList.SORT_ALPHA_DATE_NEWEST_FIRST_FLAT: self.list.sort(key=self.buildAlphaNumericFlatSortKey) elif self.sort_type == MovieList.SORT_ALPHAREV_DATE_OLDEST_FIRST_FLAT: self.list.sort(key=self.buildAlphaNumericFlatSortKey, reverse=True) elif self.sort_type == MovieList.SORT_DATE_NEWEST_FIRST_ALPHA: self.list.sort(key=self.buildBeginTimeSortKey) elif self.sort_type == MovieList.SORT_DATE_OLDEST_FIRST_ALPHAREV: self.list = sorted(self.list[:numberOfDirs], key=self.buildBeginTimeSortKey, reverse=True) \ + sorted(self.list[numberOfDirs:], key=self.buildBeginTimeSortKey, reverse=True) elif self.sort_type == MovieList.SHUFFLE: shufflelist = self.list[numberOfDirs:] random.shuffle(shufflelist) self.list = self.list[:numberOfDirs] + shufflelist elif self.sort_type == MovieList.SORT_ALPHA_DATE_OLDEST_FIRST: self.list = sorted(self.list[:numberOfDirs], key=self.buildAlphaDateSortKey) \ + sorted(self.list[numberOfDirs:], key=self.buildAlphaDateSortKey) elif self.sort_type == MovieList.SORT_ALPHAREV_DATE_NEWEST_FIRST: self.list = sorted(self.list[:numberOfDirs], key=self.buildAlphaDateSortKey, reverse=True) \ + sorted(self.list[numberOfDirs:], key=self.buildAlphaDateSortKey, reverse=True) elif self.sort_type == MovieList.SORT_SIZE_ALPHA: self.list = sorted(self.list[:numberOfDirs], key=self.buildAlphaDateSortKey) \ + sorted(self.list[numberOfDirs:], key=self.buildSizeAlphaSortKey) elif self.sort_type == MovieList.SORT_SIZEREV_ALPHA: self.list = sorted(self.list[:numberOfDirs], key=self.buildAlphaDateSortKey) \ + sorted(self.list[numberOfDirs:], key=self.buildSizeRevAlphaSortKey) elif self.sort_type == MovieList.SORT_DURATION_ALPHA: self.list = sorted(self.list[:numberOfDirs], key=self.buildAlphaDateSortKey) \ + sorted(self.list[numberOfDirs:], key=self.buildLengthAlphaSortKey) elif self.sort_type == MovieList.SORT_DURATIONREV_ALPHA: self.list = sorted(self.list[:numberOfDirs], key=self.buildAlphaDateSortKey) \ + sorted(self.list[numberOfDirs:], key=self.buildLengthRevAlphaSortKey) else: self.list.sort(key=self.buildGroupwiseSortkey) for x in self.list[:]: if x[1]: tmppath = x[1].getName(x[0])[:-1] if x[1].getName(x[0]).endswith('/') else x[1].getName(x[0]) if tmppath.endswith('.Trash'): self.list.append(self.list.pop(self.list.index(x))) else: self.list.insert(0, self.list.pop(self.list.index(x))) # Find first recording/file. Must be done after self.list has stopped changing self.firstFileEntry = 0 for index, item in enumerate(self.list): if not item[0].flags & eServiceReference.mustDescent: self.firstFileEntry = index break if self.root and numberOfDirs > 0: rootPath = os.path.normpath(self.root.getPath()) if not rootPath.endswith('/'): rootPath += '/' if rootPath != parent: # with new sort types directories may be in between files, so scan whole # list for parentDirectory index. Usually it is the first one anyway for index, item in enumerate(self.list): if item[0].flags & eServiceReference.mustDescent: itempath = os.path.normpath(item[0].getPath()) if not itempath.endswith('/'): itempath += '/' if itempath == rootPath: self.parentDirectory = index break self.root = root # finally, store a list of all tags which were found. these can be presented # to the user to filter the list # ML: Only use the tags that occur more than once in the list OR that were # really in the tag set of some file. # reverse the dictionary to see which unique movie each tag now references rautotags = {} for tag, movies in autotags.items(): if (len(movies) > 1): movies = tuple(movies) # a tuple can be hashed, but a list not item = rautotags.get(movies, []) if not item: rautotags[movies] = item item.append(tag) self.tags = {} for movies, tags in rautotags.items(): movie = movies[0] # format the tag lists so that they are in 'original' order tags.sort(key=movie.find) first = movie.find(tags[0]) last = movie.find(tags[-1]) + len(tags[-1]) match = movie start = 0 end = len(movie) # Check if the set has a complete sentence in common, and how far for m in movies[1:]: if m[start:end] != match: if not m.startswith(movie[:last]): start = first if not m.endswith(movie[first:]): end = last match = movie[start:end] if m[start:end] != match: match = '' break # Adding the longest common sentence to the tag list if match: self.tags[match] = set(tags) else: match = ' '.join(tags) if (len(match) > 2) or (match in realtags): # Omit small words, only for auto tags self.tags[match] = set(tags) # Adding the realtags to the tag list for tag in realtags: self.tags[tag] = set([tag]) def getNameKey(self, ref, info): # append the file name numeric suffix to the name, to reliably # sort recordings that have been split name = info and info.getName(ref) if name: path = ref.getPath() if path.endswith(".ts") and path[-7] == "_": name += path[-6:-3] return name and name.lower() or "" def buildAlphaNumericSortKey(self, x): # x = ref,info,begin,... ref = x[0] name = self.getNameKey(ref, x[1]) if ref.flags & eServiceReference.mustDescent: return 0, name, -x[2] return 1, name, -x[2] # as for buildAlphaNumericSortKey, but without negating dates def buildAlphaDateSortKey(self, x): # x = ref,info,begin,... ref = x[0] name = self.getNameKey(ref, x[1]) if ref.flags & eServiceReference.mustDescent: return 0, name, x[2] return 1, name, x[2] def buildAlphaNumericFlatSortKey(self, x): # x = ref,info,begin,... ref = x[0] name = self.getNameKey(ref, x[1]) or ".." if ref.flags & eServiceReference.mustDescent: # only use directory basename for sorting try: name = os.path.basename(os.path.normpath(name)) except: pass if name.endswith(".Trash"): name = _("Trash") # print "[MovieList] Sorting for -%s-" % name return 1, name, -x[2] def buildBeginTimeSortKey(self, x): ref = x[0] name = self.getNameKey(ref, x[1]) if ref.flags & eServiceReference.mustDescent and os.path.exists(ref.getPath()): try: mtime = -os.stat(ref.getPath()).st_mtime except: mtime = 0 return 0, x[1] and mtime, name return 1, -x[2], name def buildGroupwiseSortkey(self, x): # Sort recordings by date, sort MP3 and stuff by name ref = x[0] if ref.type >= eServiceReference.idUser: return self.buildAlphaNumericSortKey(x) else: return self.buildBeginTimeSortKey(x) def buildSizeAlphaSortKey(self, x): ref = x[0] info = x[1] name = self.getNameKey(ref, info) size = info and info.getFileSize(ref) return 1, size, name, -x[2] def buildSizeRevAlphaSortKey(self, x): x = self.buildSizeAlphaSortKey(x) return (x[0], -x[1], x[2], x[3]) def buildLengthAlphaSortKey(self, x): ref = x[0] info = x[1] name = self.getNameKey(ref, info) len = info and info.getLength(ref) return 1, len, name, -x[2] def buildLengthRevAlphaSortKey(self, x): x = self.buildLengthAlphaSortKey(x) return (x[0], -x[1], x[2], x[3]) def moveTo(self, serviceref): index = self.findService(serviceref) if index is not None: self.instance.moveSelectionTo(index) return True return False def moveDown(self): self.instance.moveSelection(self.instance.moveDown) def moveUp(self): self.instance.moveSelection(self.instance.moveUp) def moveToChar(self, char, lbl=None): self._char = char self._lbl = lbl if lbl: lbl.setText(self._char) lbl.visible = True self.moveToCharTimer = eTimer() self.moveToCharTimer.callback.append(self._moveToChrStr) self.moveToCharTimer.start(1000, True) # time to wait for next key press to decide which letter to use... def moveToString(self, char, lbl=None): self._char = self._char + char.upper() self._lbl = lbl if lbl: lbl.setText(self._char) lbl.visible = True self.moveToCharTimer = eTimer() self.moveToCharTimer.callback.append(self._moveToChrStr) self.moveToCharTimer.start(1000, True) # time to wait for next key press to decide which letter to use... def _moveToChrStr(self): currentIndex = self.instance.getCurrentIndex() index = currentIndex + 1 if index >= len(self.list): index = 0 while index != currentIndex: item = self.list[index] if item[1] is not None: ref = item[0] itemName = getShortName(item[1].getName(ref), ref) strlen = len(self._char) if ( strlen == 1 and itemName.startswith(self._char) or strlen > 1 and itemName.find(self._char) >= 0 ): self.instance.moveSelectionTo(index) break index += 1 if index >= len(self.list): index = 0 self._char = '' if self._lbl: self._lbl.visible = False def markItems(self, serviceList): self.markList = serviceList[:] self.refreshDisplay() def markAll(self): self.markList = [] return self.invertMarks() def markNone(self): self.markList = [] self.refreshDisplay() return 0 def toggleCurrentItem(self): item = self.l.getCurrentSelection() # don't select special items (e.g. the parent directory) if item and item[0] and item[1]: if item[0] in self.markList: self.markList.remove(item[0]) else: self.markList.append(item[0]) self.invalidateCurrentItem() return len(self.markList) def invertMarks(self): # invert the same type (directory or file) as the current cur = self.getCurrent() cur = 0 if not cur else cur.flags & eServiceReference.mustDescent for item in self.list: if item[0] and item[1] and item[0].flags & eServiceReference.mustDescent == cur: if item[0] in self.markList: self.markList.remove(item[0]) else: # don't select the trash if item[0].flags & eServiceReference.mustDescent: pathName = item[0].getPath() name = os.path.basename(os.path.normpath(pathName)) if name == '.Trash': continue self.markList.append(item[0]) self.refreshDisplay() return len(self.markList) def getMarked(self): marked = [] for service in self.markList[:]: idx = self.findService(service) if idx is not None: marked.append(self.list[idx]) else: self.markList.remove(service) return marked def countMarked(self): return len(self.getMarked())
class TimerList(GUIComponent, object): # # | <Name of the Timer> <Service> <orb.pos>| # | <state> <start, end> | # def buildTimerEntry(self, timer, processed): height = self.l.getItemSize().height() width = self.l.getItemSize().width() res = [None] piconWidth = 100 if config.usage.timerlist_showpicons.value else 0 serviceName = timer.service_ref.getServiceName() serviceNameWidth = getTextBoundarySize(self.instance, self.serviceNameFont, self.l.getItemSize(), serviceName).width() nameWidth = width - serviceNameWidth - self.iconWidth - self.iconMargin - piconWidth if nameWidth < 200: serviceNameWidth = width - 200 - self.iconWidth - self.iconMargin - piconWidth def addPicon(): refstr = None if hasattr(timer.service_ref, 'sref'): refstr = str(timer.service_ref.sref) else: refstr = str(timer.service_ref) displayPicon = None picon = getPiconName(refstr) if picon != "": displayPicon = LoadPixmap(picon) if displayPicon is not None: res.append( MultiContentEntryPixmapAlphaBlend( pos=(colX, 0), size=(piconWidth, self.itemHeight), png=displayPicon, backcolor=None, backcolor_sel=None, flags=BT_SCALE | BT_KEEP_ASPECT_RATIO | BT_ALIGN_CENTER)) return piconWidth colX = 0 if config.usage.timerlist_showpicons.value: colX += addPicon() res.append( (eListboxPythonMultiContent.TYPE_TEXT, colX + self.iconWidth + self.iconMargin, 0, nameWidth, self.rowSplit, 2, RT_HALIGN_LEFT | RT_VALIGN_BOTTOM, timer.name)) res.append( (eListboxPythonMultiContent.TYPE_TEXT, width - serviceNameWidth, 0, serviceNameWidth, self.rowSplit, 0, RT_HALIGN_RIGHT | RT_VALIGN_BOTTOM, serviceName)) begin = FuzzyTime(timer.begin) if timer.repeated: days = (_("Mon"), _("Tue"), _("Wed"), _("Thu"), _("Fri"), _("Sat"), _("Sun")) repeatedtext = [] flags = timer.repeated for x in (0, 1, 2, 3, 4, 5, 6): if flags & 1 == 1: repeatedtext.append(days[x]) flags >>= 1 if repeatedtext == [ _("Mon"), _("Tue"), _("Wed"), _("Thu"), _("Fri"), _("Sat"), _("Sun") ]: repeatedtext = _('Everyday') elif repeatedtext == [ _("Mon"), _("Tue"), _("Wed"), _("Thu"), _("Fri") ]: repeatedtext = _('Weekday') elif repeatedtext == [_("Sat"), _("Sun")]: repeatedtext = _('Weekend') else: repeatedtext = ", ".join(repeatedtext) if self.iconRepeat: res.append( (eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, colX + self.iconMargin, self.rowSplit + (self.itemHeight - self.rowSplit - self.iconHeight) / 2, self.iconWidth, self.iconHeight, self.iconRepeat)) else: repeatedtext = begin[0] # date if timer.justplay: extra_text = _("(ZAP)") if timer.pipzap: extra_text = _("(ZAP as PiP)") text = repeatedtext + ((" %s " + extra_text) % (begin[1])) else: text = repeatedtext + ((" %s ... %s (%d " + _("mins") + ")") % (begin[1], FuzzyTime(timer.end)[1], (timer.end - timer.begin) / 60)) icon = None if not processed: if timer.state == TimerEntry.StateWaiting: state = _("waiting") if timer.isAutoTimer: icon = self.iconAutoTimer else: icon = self.iconWait elif timer.state == TimerEntry.StatePrepared: state = _("about to start") icon = self.iconPrepared elif timer.state == TimerEntry.StateRunning: if timer.justplay: state = _("zapped") icon = self.iconZapped else: state = _("recording...") icon = self.iconRecording elif timer.state == TimerEntry.StateEnded: state = _("done!") icon = self.iconDone else: state = _("<unknown>") icon = None elif timer.disabled: state = _("disabled") icon = self.iconDisabled elif timer.failed: state = _("failed") icon = self.iconFailed else: state = _("done!") icon = self.iconDone icon and res.append( (eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, colX + self.iconMargin / 2, (self.rowSplit - self.iconHeight) / 2, self.iconWidth, self.iconHeight, icon)) orbpos = self.getOrbitalPos(timer.service_ref) orbposWidth = getTextBoundarySize(self.instance, self.font, self.l.getItemSize(), orbpos).width() res.append( (eListboxPythonMultiContent.TYPE_TEXT, colX + self.satPosLeft, self.rowSplit, orbposWidth, self.itemHeight - self.rowSplit, 1, RT_HALIGN_LEFT | RT_VALIGN_TOP, orbpos)) res.append((eListboxPythonMultiContent.TYPE_TEXT, colX + self.iconWidth + self.iconMargin, self.rowSplit, self.satPosLeft - self.iconWidth - self.iconMargin, self.itemHeight - self.rowSplit, 1, RT_HALIGN_LEFT | RT_VALIGN_TOP, state)) res.append((eListboxPythonMultiContent.TYPE_TEXT, colX + self.satPosLeft + orbposWidth, self.rowSplit, width - self.satPosLeft - orbposWidth - colX, self.itemHeight - self.rowSplit, 1, RT_HALIGN_RIGHT | RT_VALIGN_TOP, text)) line = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "div-h.png")) res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, 0, height - 2, width, 2, line)) return res def __init__(self, list): GUIComponent.__init__(self) self.l = eListboxPythonMultiContent() self.l.setBuildFunc(self.buildTimerEntry) self.serviceNameFont = gFont("Regular", 20) self.font = gFont("Regular", 18) self.eventNameFont = gFont("Regular", 18) self.l.setList(list) self.itemHeight = 50 self.rowSplit = 25 self.iconMargin = 4 self.satPosLeft = 160 self.iconWait = LoadPixmap( resolveFilename(SCOPE_CURRENT_SKIN, "icons/timer_wait.png")) #currently intended that all icons have the same size self.iconWidth = self.iconWait.size().width() self.iconHeight = self.iconWait.size().height() self.iconRecording = LoadPixmap( resolveFilename(SCOPE_CURRENT_SKIN, "icons/timer_rec.png")) self.iconPrepared = LoadPixmap( resolveFilename(SCOPE_CURRENT_SKIN, "icons/timer_prep.png")) self.iconDone = LoadPixmap( resolveFilename(SCOPE_CURRENT_SKIN, "icons/timer_done.png")) self.iconRepeat = LoadPixmap( resolveFilename(SCOPE_CURRENT_SKIN, "icons/timer_rep.png")) self.iconZapped = LoadPixmap( resolveFilename(SCOPE_CURRENT_SKIN, "icons/timer_zap.png")) self.iconDisabled = LoadPixmap( resolveFilename(SCOPE_CURRENT_SKIN, "icons/timer_off.png")) self.iconFailed = LoadPixmap( resolveFilename(SCOPE_CURRENT_SKIN, "icons/timer_failed.png")) self.iconAutoTimer = LoadPixmap( resolveFilename(SCOPE_CURRENT_SKIN, "icons/timer_autotimer.png")) def applySkin(self, desktop, parent): def itemHeight(value): self.itemHeight = parseScale(value) def setServiceNameFont(value): self.serviceNameFont = parseFont(value, ((1, 1), (1, 1))) def setEventNameFont(value): self.eventNameFont = parseFont(value, ((1, 1), (1, 1))) def setFont(value): self.font = parseFont(value, ((1, 1), (1, 1))) def rowSplit(value): self.rowSplit = parseScale(value) def iconMargin(value): self.iconMargin = parseScale(value) def satPosLeft(value): self.satPosLeft = parseScale(value) for (attrib, value) in list(self.skinAttributes): try: locals().get(attrib)(value) self.skinAttributes.remove((attrib, value)) except: pass self.l.setItemHeight(self.itemHeight) self.l.setFont(0, self.serviceNameFont) self.l.setFont(1, self.font) self.l.setFont(2, self.eventNameFont) return GUIComponent.applySkin(self, desktop, parent) def getCurrent(self): cur = self.l.getCurrentSelection() return cur and cur[0] GUI_WIDGET = eListbox def postWidgetCreate(self, instance): instance.setContent(self.l) self.instance = instance instance.setWrapAround(True) def moveToIndex(self, index): self.instance.moveSelectionTo(index) def getCurrentIndex(self): return self.instance.getCurrentIndex() currentIndex = property(getCurrentIndex, moveToIndex) currentSelection = property(getCurrent) def moveDown(self): self.instance.moveSelection(self.instance.moveDown) def invalidate(self): self.l.invalidate() def entryRemoved(self, idx): self.l.entryRemoved(idx) def getOrbitalPos(self, ref): refstr = None if hasattr(ref, 'sref'): refstr = str(ref.sref) else: refstr = str(ref) refstr = refstr and GetWithAlternative(refstr) if '%3a//' in refstr: return "%s" % _("Stream") op = int(refstr.split(':', 10)[6][:-4] or "0", 16) if op == 0xeeee: return "%s" % _("DVB-T") if op == 0xffff: return "%s" % _("DVB-C") direction = 'E' if op > 1800: op = 3600 - op direction = 'W' return ("%d.%d\xc2\xb0%s") % (op // 10, op % 10, direction)
def VirtualKeyBoardEntryComponent(keys, selectedKey, shiftMode=False): key_backspace = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_backspace.png")) key_bg = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_bg.png")) key_clr = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_clr.png")) key_esc = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_esc.png")) key_ok = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_ok.png")) key_sel = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_sel.png")) key_shift = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_shift.png")) key_shift_sel = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_shift_sel.png")) key_space = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_space.png")) res = [(keys)] x = 0 count = 0 if shiftMode: shiftkey_png = key_shift_sel else: shiftkey_png = key_shift for key in keys: width = None if key == "EXIT": width = key_esc.size().width() res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=key_esc)) elif key == "BACKSPACE": width = key_backspace.size().width() res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=key_backspace)) elif key == "CLEAR": width = key_clr.size().width() res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=key_clr)) elif key == "SHIFT": width = shiftkey_png.size().width() res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=shiftkey_png)) elif key == "SPACE": width = key_space.size().width() res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=key_space)) elif key == "OK": width = key_ok.size().width() res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=key_ok)) # elif key == "<-": # res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(45, 45), png=key_left)) # elif key == "->": # res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(45, 45), png=key_right)) else: width = key_bg.size().width() res.extend( ( MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=key_bg), MultiContentEntryText( pos=(x, 0), size=(width, 45), font=0, text=key.encode("utf-8"), flags=RT_HALIGN_CENTER | RT_VALIGN_CENTER, ), ) ) if selectedKey == count: width = key_sel.size().width() res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=key_sel)) if width is not None: x += width else: x += 45 count += 1 return res
class IPTVVirtualKeyBoardWithCaptcha(Screen): def __init__(self, session, title="", text="", additionalParams={}): winWidth = 590 self.skin = '''<screen position="center,center" size="%d,500" title="" > <widget name="captcha" position="%d,%d" size="%d,%d" zPosition="2" transparent="1" alphatest="on" /> <widget name="key_red" position="10,10" zPosition="2" size="%d,35" valign="center" halign="left" font="Regular;22" transparent="1" foregroundColor="red" /> <widget name="key_ok" position="10,10" zPosition="2" size="%d,35" valign="center" halign="center" font="Regular;22" transparent="1" foregroundColor="white" /> <widget name="key_green" position="10,10" zPosition="2" size="%d,35" valign="center" halign="right" font="Regular;22" transparent="1" foregroundColor="green" /> <ePixmap pixmap="%s" position="25,195" size="542,80" zPosition="-4" alphatest="on" /> <widget name="header" position="25,160" size="500,26" transparent="1" noWrap="1" font="Regular;20" valign="top"/> <widget name="text" position="25,200" size="536,34" transparent="1" noWrap="1" font="Regular;26" valign="center" halign="right" /> <widget name="list" position="25,250" size="550,225" selectionDisabled="1" transparent="1" /> </screen> ''' % ( winWidth, 10, 55, \ winWidth - 20, 100, \ winWidth-20, \ winWidth-20, \ winWidth-20, \ GetIconDir("vk/vkey_text.png")) Screen.__init__(self, session) self.keys_list = [] self.shiftkeys_list = [] self.shiftMode = additionalParams.get('shift_mode', False) self.selectedKey = 0 self.smsChar = None self.sms = NumericalTextInput(self.smsOK) self.key_bg = LoadPixmap(GetIconDir("vk/vkey_bg.png")) self.key_sel = LoadPixmap(GetIconDir("vk/vkey_sel.png")) self.key_backspace = LoadPixmap(GetIconDir("vk/vkey_backspace.png")) self.key_all = LoadPixmap(GetIconDir("vk/vkey_all.png")) self.key_clr = LoadPixmap(GetIconDir("vk/vkey_clr.png")) self.key_esc = LoadPixmap(GetIconDir("vk/vkey_esc.png")) self.key_ok = LoadPixmap(GetIconDir("vk/vkey_ok.png")) self.key_shift = LoadPixmap(GetIconDir("vk/vkey_shift.png")) self.key_shift_sel = LoadPixmap(GetIconDir("vk/vkey_shift_sel.png")) self.key_space = LoadPixmap(GetIconDir("vk/vkey_space.png")) self.key_left = LoadPixmap(GetIconDir("vk/vkey_left.png")) self.key_right = LoadPixmap(GetIconDir("vk/vkey_right.png")) self.keyImages = { "BACKSPACE": self.key_backspace, "CLEAR": self.key_clr, "ALL": self.key_all, "EXIT": self.key_esc, "OK": self.key_ok, "SHIFT": self.key_shift, "SPACE": self.key_space, "LEFT": self.key_left, "RIGHT": self.key_right } self.keyImagesShift = { "BACKSPACE": self.key_backspace, "CLEAR": self.key_clr, "ALL": self.key_all, "EXIT": self.key_esc, "OK": self.key_ok, "SHIFT": self.key_shift_sel, "SPACE": self.key_space, "LEFT": self.key_left, "RIGHT": self.key_right } self["key_green"] = Label(_("Accept")) self["key_ok"] = Label(_("OK")) self["key_red"] = Label(_("Cancel")) self["header"] = Label(title) self["text"] = Input(text=text.decode("utf-8", 'ignore')) self["list"] = VirtualKeyBoardList([]) self["actions"] = NumberActionMap( [ "OkCancelActions", "WizardActions", "ColorActions", "KeyboardInputActions", "InputBoxActions", "InputAsciiActions" ], { "gotAsciiCode": self.keyGotAscii, "ok": self.okClicked, "cancel": self.exit, "left": self.left, "right": self.right, "up": self.up, "down": self.down, "red": self.exit, "green": self.ok, "yellow": self.switchLang, "blue": self.shiftClicked, "deleteBackward": self.backClicked, "deleteForward": self.forwardClicked, "back": self.exit, "pageUp": self.cursorRight, "pageDown": self.cursorLeft, "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, }, -2) self.startText = text self.setLang(additionalParams) self.onExecBegin.append(self.setKeyboardModeAscii) self.onLayoutFinish.append(self.buildVirtualKeyBoard) self.captchaPath = additionalParams['captcha_path'] self['captcha'] = Cover2() self.onShown.append(self.loadCaptcha) def loadCaptcha(self): self.onShown.remove(self.loadCaptcha) self.setTitle(_('Virtual Keyboard')) self["text"].right() self["text"].currPos = len(self.startText) self["text"].right() try: self['captcha'].updateIcon(self.captchaPath) except Exception: printExc() def switchLang(self): pass def setLang(self, additionalParams): if 'keys_list' not in additionalParams: self.keys_list = [[ u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE" ], [ u"q", u"w", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"-", u"[" ], [ u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u";", u"'", u"\\" ], [ u"<", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"/", u"CLEAR" ], [u"SHIFT", u"SPACE", u"OK", u"LEFT", u"RIGHT"]] else: self.keys_list = additionalParams['keys_list'] if 'shiftkeys_list' not in additionalParams: self.shiftkeys_list = [[ u"EXIT", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"(", u")", u"=", u"BACKSPACE" ], [ u"Q", u"W", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"*", u"]" ], [ u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"?", u'"', u"|" ], [ u">", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR" ], [ u"SHIFT", u"SPACE", u"OK", u"LEFT", u"RIGHT" ]] else: self.keys_list = additionalParams['shiftkeys_list'] if additionalParams.get('invert_letters_case', False): for keys_list in [self.keys_list, self.shiftkeys_list]: for row in range(len(keys_list)): for idx in range(len(keys_list[row])): if len(keys_list[row][idx]) != 1: continue upper = keys_list[row][idx].upper() if upper == keys_list[row][idx]: keys_list[row][idx] = keys_list[row][idx].lower() else: keys_list[row][idx] = upper self.max_key = 47 + len(self.keys_list[4]) def virtualKeyBoardEntryComponent(self, keys): key_bg_width = self.key_bg and self.key_bg.size().width() or 45 key_images = self.shiftMode and self.keyImagesShift or self.keyImages res = [(keys)] text = [] x = 0 for key in keys: png = key_images.get(key, None) if png: width = png.size().width() res.append( MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=png)) else: width = key_bg_width res.append( MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=self.key_bg)) text.append( MultiContentEntryText(pos=(x, 0), size=(width, 45), font=0, text=key.encode("utf-8"), flags=RT_HALIGN_CENTER | RT_VALIGN_CENTER)) x += width return res + text def buildVirtualKeyBoard(self): self.previousSelectedKey = None self.list = [] for keys in self.shiftMode and self.shiftkeys_list or self.keys_list: self.list.append(self.virtualKeyBoardEntryComponent(keys)) self.markSelectedKey() def markSelectedKey(self): if self.previousSelectedKey is not None: self.list[self.previousSelectedKey / 12] = self.list[self.previousSelectedKey / 12][:-1] width = self.key_sel.size().width() x = self.list[self.selectedKey / 12][self.selectedKey % 12 + 1][1] self.list[self.selectedKey / 12].append( MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=self.key_sel)) self.previousSelectedKey = self.selectedKey self["list"].setList(self.list) def backClicked(self): self["text"].deleteBackward() def forwardClicked(self): self["text"].deleteForward() def shiftClicked(self): self.smsChar = None self.shiftMode = not self.shiftMode self.buildVirtualKeyBoard() def okClicked(self): self.smsChar = None text = (self.shiftMode and self.shiftkeys_list or self.keys_list)[self.selectedKey / 12][self.selectedKey % 12].encode("UTF-8") if text == "EXIT": self.close(None) elif text == "BACKSPACE": self["text"].deleteBackward() elif text == "ALL": self["text"].setMarkedPos(-2) elif text == "CLEAR": self["text"].deleteAllChars() self["text"].update() elif text == "SHIFT": self.shiftClicked() elif text == "SPACE": self["text"].insertChar(" ".encode("UTF-8"), self["text"].currPos, False, True) self["text"].innerright() self["text"].update() elif text == "OK": self.close(self["text"].getText().encode("UTF-8")) elif text == "LEFT": self["text"].left() elif text == "RIGHT": self["text"].right() else: self["text"].insertChar(text, self["text"].currPos, False, True) self["text"].innerright() self["text"].update() def ok(self): self.close(self["text"].getText()) def exit(self): self.close(None) def cursorRight(self): self["text"].right() def cursorLeft(self): self["text"].left() def left(self): self.smsChar = None self.selectedKey = self.selectedKey / 12 * 12 + (self.selectedKey + 11) % 12 if self.selectedKey > self.max_key: self.selectedKey = self.max_key self.markSelectedKey() def right(self): self.smsChar = None self.selectedKey = self.selectedKey / 12 * 12 + (self.selectedKey + 1) % 12 if self.selectedKey > self.max_key: self.selectedKey = self.selectedKey / 12 * 12 self.markSelectedKey() def up(self): self.smsChar = None self.selectedKey -= 12 if self.selectedKey < 0: self.selectedKey = self.max_key / 12 * 12 + self.selectedKey % 12 if self.selectedKey > self.max_key: self.selectedKey -= 12 self.markSelectedKey() def down(self): self.smsChar = None self.selectedKey += 12 if self.selectedKey > self.max_key: self.selectedKey = self.selectedKey % 12 self.markSelectedKey() def keyNumberGlobal(self, number): self.smsChar = self.sms.getKey(number) self.selectAsciiKey(self.smsChar) def smsOK(self): if self.smsChar and self.selectAsciiKey(self.smsChar): self.okClicked() def keyGotAscii(self): self.smsChar = None if self.selectAsciiKey(str(unichr( getPrevAsciiCode()).encode('utf-8'))): self.okClicked() def selectAsciiKey(self, char): if char == " ": char = "SPACE" for keyslist in (self.shiftkeys_list, self.keys_list): selkey = 0 for keys in keyslist: for key in keys: if key == char: self.selectedKey = selkey if self.shiftMode != (keyslist is self.shiftkeys_list): self.shiftMode = not self.shiftMode self.buildVirtualKeyBoard() else: self.markSelectedKey() return True selkey += 1 return False
class AutoTimerList(MenuList): """Defines a simple Component to show Timer name""" # # | <timername> <timespan> | line 'EventNameFont' # | <timeframe> <days> | line 'DayNameFont' # | <servicename> | line 'ServiceNameFont' # def __init__(self, entries): MenuList.__init__(self, entries, False, content = eListboxPythonMultiContent) self.l.setBuildFunc(self.buildListboxEntry) try: png = resolveFilename(SCOPE_CURRENT_SKIN, "icons/lock_off.png") except: png = resolveFilename(SCOPE_CURRENT_SKIN, "skin-default/icons/lock_off.png") self.iconDisabled = LoadPixmap(cached=True, path=png) #currently intended that all icons have the same size try: png = resolveFilename(SCOPE_CURRENT_SKIN, "icons/lock_on.png") except: png = resolveFilename(SCOPE_CURRENT_SKIN, "skin-default/icons/lock_on.png") self.iconEnabled = LoadPixmap(cached=True, path=png) try: png = resolveFilename(SCOPE_CURRENT_SKIN, "icons/timer_rec.png") except: png = resolveFilename(SCOPE_CURRENT_SKIN, "skin-default/icons/timer_rec.png") self.iconRecording = LoadPixmap(cached=True, path=png) try: png = resolveFilename(SCOPE_CURRENT_SKIN, "icons/timer_zap.png") except: png = resolveFilename(SCOPE_CURRENT_SKIN, "skin-default/icons/timer_zap.png") self.iconZapped = LoadPixmap(cached=True, path=png) self.ServiceNameFont = gFont("Regular", 20) self.EventNameFont = gFont("Regular", 20) self.DayNameFont = gFont("Regular", 18) self.itemHeight = 75 self.rowHeight = 24 self.rowSplit1 = 26 self.rowSplit2 = 47 self.statusIconWidth = self.iconEnabled.size().width() self.statusIconHeight = self.iconEnabled.size().height() self.typeIconWidth = self.iconRecording.size().width() self.typeIconHeight = self.iconRecording.size().height() self.iconMargin = 2 def applySkin(self, desktop, parent): def itemHeight(value): self.itemHeight = int(value) def ServiceNameFont(value): self.ServiceNameFont = parseFont(value, ((1,1),(1,1))) def EventNameFont(value): self.EventNameFont = parseFont(value, ((1,1),(1,1))) def DayNameFont(value): self.DayNameFont = parseFont(value, ((1,1),(1,1))) def rowHeight(value): self.rowHeight = int(value) def rowSplit1(value): self.rowSplit1 = int(value) def rowSplit2(value): self.rowSplit2 = int(value) def iconMargin(value): self.iconMargin = int(value) for (attrib, value) in list(self.skinAttributes): try: locals().get(attrib)(value) self.skinAttributes.remove((attrib, value)) except: pass self.l.setItemHeight(self.itemHeight) self.l.setFont(0, self.ServiceNameFont) self.l.setFont(1, self.EventNameFont) self.l.setFont(2, self.DayNameFont) return MenuList.applySkin(self, desktop, parent) def buildListboxEntry(self, timer): if not timer.enabled: icon = self.iconDisabled else: icon = self.iconEnabled if timer.justplay: rectypeicon = self.iconZapped else: rectypeicon = self.iconRecording height = self.l.getItemSize().height() width = self.l.getItemSize().width() iconMargin = self.iconMargin statusIconHeight = self.statusIconHeight statusIconWidth = self.statusIconWidth typeIconHeight = self.typeIconHeight typeIconWidth = self.typeIconWidth rowHeight = self.rowHeight rowSplit1 = self.rowSplit1 rowSplit2 = self.rowSplit2 channels = [] bouquets = [] for t in timer.services: channels.append(ServiceReference(t).getServiceName()) for t in timer.bouquets: bouquets.append(ServiceReference(t).getServiceName()) if len(channels) >0 : channel = _("[S] ") channel += ", ".join(channels) elif len(bouquets) >0 : channel = _("[B] ") channel += ", ".join(bouquets) else: channel = _('All channels') res = [ None ] if icon: if skinparms: x, y, w, h = parameters.get("AutotimerEnabledIcon",(iconMargin, 0, statusIconHeight, statusIconWidth)) else: x, y, w, h = (iconMargin, 0, statusIconHeight, statusIconWidth) res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, x, y, w, h, icon)) if rectypeicon: if skinparms: x, y, w, h = parameters.get("AutotimerRecordIcon",(iconMargin+statusIconWidth+iconMargin, 3, statusIconHeight, typeIconWidth)) else: x, y, w, h = (iconMargin+statusIconWidth+iconMargin, 3, statusIconHeight, typeIconWidth) res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, x, y, w, h, rectypeicon)) if timer.hasTimespan(): nowt = time() now = localtime(nowt) begintime = int(mktime((now.tm_year, now.tm_mon, now.tm_mday, timer.timespan[0][0], timer.timespan[0][1], 0, now.tm_wday, now.tm_yday, now.tm_isdst))) endtime = int(mktime((now.tm_year, now.tm_mon, now.tm_mday, timer.timespan[1][0], timer.timespan[1][1], 0, now.tm_wday, now.tm_yday, now.tm_isdst))) timespan = ((" %s ... %s") % (FuzzyTime(begintime)[1], FuzzyTime(endtime)[1])) else: timespan = _(" Any time") res.append((eListboxPythonMultiContent.TYPE_TEXT, float(width)/10*4.5, 2, width-float(width)/10*4.5, rowHeight, 1, RT_HALIGN_RIGHT|RT_VALIGN_BOTTOM, timespan)) if TextBoundary: timespanWidth = getTextBoundarySize(self.instance, self.EventNameFont, self.l.getItemSize(), timespan).width() else: timespanWidth = float(width)/10*2 res.append((eListboxPythonMultiContent.TYPE_TEXT, statusIconWidth+typeIconWidth+iconMargin*3, 2, width-statusIconWidth-typeIconWidth-iconMargin*3- timespanWidth, rowHeight, 1, RT_HALIGN_LEFT|RT_VALIGN_BOTTOM, timer.name)) if timer.hasTimeframe(): begin = strftime("%a, %d %b", localtime(timer.getTimeframeBegin())) end = strftime("%a, %d %b", localtime(timer.getTimeframeEnd())) timeframe = (("%s ... %s") % (begin, end)) res.append((eListboxPythonMultiContent.TYPE_TEXT, iconMargin, rowSplit1, float(width)/10*4.5, rowHeight, 2, RT_HALIGN_LEFT|RT_VALIGN_TOP, timeframe)) if timer.include[3]: total = len(timer.include[3]) count = 0 days = [] while count+1 <= total: day = timer.include[3][count] day = { '0': _("Mon"), '1': _("Tue"), '2': _("Wed"), '3': _("Thur"), '4': _("Fri"), '5': _("Sat"), '6': _("Sun"), "weekend": _("Weekend"), "weekday": _("Weekday") }[day] days.append(day) count += 1 days = ', '.join(days) else: days = _("Everyday") res.append((eListboxPythonMultiContent.TYPE_TEXT, float(width)/10*5.5, rowSplit1, width-float(width)/10*5.5, rowHeight, 2, RT_HALIGN_RIGHT|RT_VALIGN_TOP, days)) res.append((eListboxPythonMultiContent.TYPE_TEXT, iconMargin, rowSplit2, width-(iconMargin*2), rowHeight, 0, RT_HALIGN_LEFT|RT_VALIGN_TOP, channel)) try: devide = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "div-h.png")) except: devide = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "div-h.png")) res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, 0, height-2, width, 2, devide)) return res def getCurrent(self): cur = self.l.getCurrentSelection() return cur and cur[0] def moveToEntry(self, entry): if entry is None: return idx = 0 for x in self.list: if x[0] == entry: self.instance.moveSelectionTo(idx) break idx += 1
class PowerTimerList(HTMLComponent, GUIComponent, object): def buildTimerEntry(self, timer, processed): height = self.l.getItemSize().height() width = self.l.getItemSize().width() res = [None] res.append((eListboxPythonMultiContent.TYPE_TEXT, self.iconWidth + self.iconMargin, 0, width, self.rowSplit, 0, RT_HALIGN_LEFT | RT_VALIGN_BOTTOM, gettimerType(timer))) if timer.timerType == TIMERTYPE.AUTOSTANDBY or timer.timerType == TIMERTYPE.AUTODEEPSTANDBY: if self.iconRepeat and timer.autosleeprepeat != 'once': res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, self.iconMargin / 2, self.rowSplit + (self.itemHeight - self.rowSplit - self.iconHeight) / 2, self.iconWidth, self.iconHeight, self.iconRepeat)) icon = None if not processed: if timer.state == TimerEntry.StateWaiting: state = _('waiting') icon = self.iconWait elif timer.state == TimerEntry.StatePrepared or timer.state == TimerEntry.StateRunning: state = _('running...') icon = self.iconZapped elif timer.state == TimerEntry.StateEnded: state = _('done!') icon = self.iconDone else: state = _('<unknown>') icon = None else: state = _('done!') icon = self.iconDone autosleepwindow = '' if timer.autosleepwindow == 'yes': autosleepwindow = _('Time range:') + ' ' + FuzzyTime(timer.autosleepbegin)[1] + ' ... ' + FuzzyTime(timer.autosleepend)[1] + ', ' res.append((eListboxPythonMultiContent.TYPE_TEXT, self.satPosLeft, self.rowSplit, width - self.satPosLeft, self.itemHeight - self.rowSplit, 1, RT_HALIGN_RIGHT | RT_VALIGN_TOP, autosleepwindow + _('Delay:') + ' ' + str(timer.autosleepdelay) + '(' + _('mins') + ')')) else: res.append((eListboxPythonMultiContent.TYPE_TEXT, self.satPosLeft, 0, width - self.satPosLeft, self.rowSplit, 2, RT_HALIGN_RIGHT | RT_VALIGN_BOTTOM, _('At End:') + ' ' + getafterEvent(timer))) begin = FuzzyTime(timer.begin) if timer.repeated: days = ( _('Mon'), _('Tue'), _('Wed'), _('Thu'), _('Fri'), _('Sat'), _('Sun')) repeatedtext = [] flags = timer.repeated for x in (0, 1, 2, 3, 4, 5, 6): if flags & 1 == 1: repeatedtext.append(days[x]) flags >>= 1 if repeatedtext == [_('Mon'), _('Tue'), _('Wed'), _('Thu'), _('Fri'), _('Sat'), _('Sun')]: repeatedtext = _('Everyday') elif repeatedtext == [_('Mon'), _('Tue'), _('Wed'), _('Thu'), _('Fri')]: repeatedtext = _('Weekday') elif repeatedtext == [_('Sat'), _('Sun')]: repeatedtext = _('Weekend') else: repeatedtext = ', '.join(repeatedtext) if self.iconRepeat: res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, self.iconMargin / 2, self.rowSplit + (self.itemHeight - self.rowSplit - self.iconHeight) / 2, self.iconWidth, self.iconHeight, self.iconRepeat)) else: repeatedtext = begin[0] text = repeatedtext + (' %s ... %s (%d ' + _('mins') + ')') % (begin[1], FuzzyTime(timer.end)[1], (timer.end - timer.begin) / 60) res.append((eListboxPythonMultiContent.TYPE_TEXT, self.satPosLeft, self.rowSplit, width - self.satPosLeft, self.itemHeight - self.rowSplit, 1, RT_HALIGN_RIGHT | RT_VALIGN_TOP, text)) icon = None if not processed: if timer.state == TimerEntry.StateWaiting: state = _('waiting') icon = self.iconWait elif timer.state == TimerEntry.StatePrepared: state = _('about to start') icon = self.iconPrepared elif timer.state == TimerEntry.StateRunning: state = _('running...') icon = self.iconZapped elif timer.state == TimerEntry.StateEnded: state = _('done!') icon = self.iconDone else: state = _('<unknown>') icon = None else: state = _('done!') icon = self.iconDone if timer.disabled: state = _('disabled') icon = self.iconDisabled if timer.failed: state = _('failed') icon = self.iconFailed icon and res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, self.iconMargin / 2, (self.rowSplit - self.iconHeight) / 2, self.iconWidth, self.iconHeight, icon)) res.append((eListboxPythonMultiContent.TYPE_TEXT, self.iconWidth + self.iconMargin, self.rowSplit, self.satPosLeft - self.iconWidth - self.iconMargin, self.itemHeight - self.rowSplit, 1, RT_HALIGN_LEFT | RT_VALIGN_TOP, state)) line = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, 'div-h.png')) res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, 0, height - 2, width, 2, line)) return res def __init__(self, list): GUIComponent.__init__(self) self.l = eListboxPythonMultiContent() self.l.setBuildFunc(self.buildTimerEntry) self.serviceNameFont = gFont('Regular', 20) self.font = gFont('Regular', 18) self.eventNameFont = gFont('Regular', 18) self.l.setList(list) self.itemHeight = 50 self.rowSplit = 25 self.iconMargin = 4 self.satPosLeft = 160 self.iconWait = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/timer_wait.png')) self.iconWidth = self.iconWait.size().width() self.iconHeight = self.iconWait.size().height() self.iconRecording = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/timer_rec.png')) self.iconPrepared = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/timer_prep.png')) self.iconDone = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/timer_done.png')) self.iconRepeat = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/timer_rep.png')) self.iconZapped = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/timer_zap.png')) self.iconDisabled = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/timer_off.png')) self.iconFailed = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/timer_failed.png')) def applySkin(self, desktop, parent): def itemHeight(value): self.itemHeight = int(value) def setServiceNameFont(value): self.serviceNameFont = parseFont(value, ((1, 1), (1, 1))) def setEventNameFont(value): self.eventNameFont = parseFont(value, ((1, 1), (1, 1))) def setFont(value): self.font = parseFont(value, ((1, 1), (1, 1))) def rowSplit(value): self.rowSplit = int(value) def iconMargin(value): self.iconMargin = int(value) def satPosLeft(value): self.satPosLeft = int(value) for attrib, value in list(self.skinAttributes): try: locals().get(attrib)(value) self.skinAttributes.remove((attrib, value)) except: pass self.l.setItemHeight(self.itemHeight) self.l.setFont(0, self.serviceNameFont) self.l.setFont(1, self.font) self.l.setFont(2, self.eventNameFont) return GUIComponent.applySkin(self, desktop, parent) def getCurrent(self): cur = self.l.getCurrentSelection() return cur and cur[0] GUI_WIDGET = eListbox def postWidgetCreate(self, instance): instance.setContent(self.l) self.instance = instance def moveToIndex(self, index): self.instance.moveSelectionTo(index) def getCurrentIndex(self): return self.instance.getCurrentIndex() currentIndex = property(getCurrentIndex, moveToIndex) currentSelection = property(getCurrent) def moveDown(self): self.instance.moveSelection(self.instance.moveDown) def invalidate(self): self.l.invalidate() def entryRemoved(self, idx): self.l.entryRemoved(idx)
class VirtualKeyBoard(Screen, HelpableScreen): def __init__(self, session, title=_("Virtual KeyBoard Text:"), text="", maxSize=False, visible_width=False, type=Input.TEXT, currPos=0, allMarked=False): Screen.__init__(self, session) HelpableScreen.__init__(self) self.setTitle(_("Virtual keyboard")) prompt = title # Title should only be used for screen titles! self.key_bg = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_bg.png")) self.key_red_bg = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_red.png")) self.key_green_bg = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_green.png")) self.key_yellow_bg = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_yellow.png")) self.key_blue_bg = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_blue.png")) self.key_sel = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_sel.png")) self.key_backspace = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_backspace.png")) self.key_enter = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_enter.png")) self.key_first = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_first.png")) self.key_last = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_last.png")) self.key_left = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_left.png")) self.key_right = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_right.png")) self.key_shift0 = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_shift0.png")) self.key_shift1 = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_shift1.png")) self.key_shift2 = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_shift2.png")) self.key_shift3 = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_shift3.png")) self.key_space = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_space.png")) self.key_space_alt = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "buttons/vkey_space_alt.png")) self.keyBackgrounds = { "EXIT": self.key_red_bg, "OK": self.key_green_bg, "SAVE": self.key_green_bg, "LOC": self.key_yellow_bg, "SHFT": self.key_blue_bg } self.keyImages = [{ "BACKSPACE": self.key_backspace, "ENTER": self.key_enter, "FIRST": self.key_first, "LAST": self.key_last, "LEFT": self.key_left, "RIGHT": self.key_right, "SHIFT": self.key_shift0, "SPACE": self.key_space_alt }, { "BACKSPACE": self.key_backspace, "ENTER": self.key_enter, "FIRST": self.key_first, "LAST": self.key_last, "LEFT": self.key_left, "RIGHT": self.key_right, "SHIFT": self.key_shift1, "SPACE": self.key_space_alt }, { "BACKSPACE": self.key_backspace, "ENTER": self.key_enter, "FIRST": self.key_first, "LAST": self.key_last, "LEFT": self.key_left, "RIGHT": self.key_right, "SHIFT": self.key_shift2, "SPACE": self.key_space_alt }, { "BACKSPACE": self.key_backspace, "ENTER": self.key_enter, "FIRST": self.key_first, "LAST": self.key_last, "LEFT": self.key_left, "RIGHT": self.key_right, "SHIFT": self.key_shift3, "SPACE": self.key_space_alt }] self.shiftMsgs = [ _("Lower case"), _("Upper case"), _("Special 1"), _("Special 2") ] self.english = [ [ [u"`", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"-", u"=", u"BACKSPACE"], [u"FIRST", u"q", u"w", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"[", u"]", u"\\"], [u"LAST", u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u";", u"'", u"", u"ENTER"], [u"SHIFT", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", u".", u"/", u"", u"", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ], [ [u"~", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"*", u"(", u")", u"_", u"+", u"BACKSPACE"], [u"FIRST", u"Q", u"W", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"{", u"}", u"|"], [u"LAST", u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u":", u"\"", u"", u"ENTER"], [u"SHIFT", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u"<", u">", u"?", u"", u"", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ] ] self.french = [ [ [u"\u00B2", u"&", u"\u00E9", u"\"", u"'", u"(", u"-", u"\u00E8", u"_", u"\u00E7", u"\u00E0", u")", u"=", u"BACKSPACE"], [u"FIRST", u"a", u"z", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"$", u"[", u"]"], [u"LAST", u"q", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"m", u"\u00F9", u"*", u"ENTER"], [u"SHIFT", u"<", u"w", u"x", u"c", u"v", u"b", u"n", u",", u";", u":", u"!", u"\u20AC", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE", u"#", u"@", u"`"] ], [ [u"", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"\u00B0", u"+", u"BACKSPACE"], [u"FIRST", u"A", u"Z", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"\u00A3", u"{", u"}"], [u"LAST", u"Q", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"M", u"%", u"\u00B5", u"ENTER"], [u"SHIFT", u">", u"W", u"X", u"C", u"V", u"B", u"N", u"?", u".", u"/", u"\u00A7", u"\u00A6", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE", u"~", u"^", u"\\"] ], [ [u"", u"", u"\u00E2", u"\u00EA", u"\u00EE", u"\u00F4", u"\u00FB", u"\u00E4", u"\u00EB", u"\u00EF", u"\u00F6", u"\u00FC", u"", u"BACKSPACE"], [u"FIRST", u"", u"\u00E0", u"\u00E8", u"\u00EC", u"\u00F2", u"\u00F9", u"\u00E1", u"\u00E9", u"\u00ED", u"\u00F3", u"\u00FA", u"", u""], [u"LAST", u"", u"\u00C2", u"\u00CA", u"\u00CE", u"\u00D4", u"\u00DB", u"\u00C4", u"\u00CB", u"\u00CF", u"\u00D6", u"\u00DC", u"", u"ENTER"], [u"SHIFT", u"", u"\u00C0", u"\u00C8", u"\u00CC", u"\u00D2", u"\u00D9", u"\u00C1", u"\u00C9", u"\u00CD", u"\u00D3", u"\u00DA", u"", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ] ] self.german = [ [ [u"", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"\u00DF", u"'", u"BACKSPACE"], [u"FIRST", u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"\u00FC", u"[", u"]"], [u"LAST", u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"\u00F6", u"\u00E4", u"+", U"ENTER"], [u"SHIFT", u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"#", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE", u"|", u"\\", u"\u00B5"] ], [ [u"\u00B0", u"!", u"\"", u"\u00A7", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"?", u"`", u"BACKSPACE"], [u"FIRST", u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"\u00DC", u"{", u"}"], [u"LAST", u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"\u00D6", u"\u00C4", u"*", U"ENTER"], [u"SHIFT", u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"@", U"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE", u"\u20AC", u"\u00B2", u"\u00B3"] ] ] self.russian = [ [ [u"\u0451", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"-", u"=", u"BACKSPACE"], [u"FIRST", u"\u0439", u"\u0446", u"\u0443", u"\u043A", u"\u0435", u"\u043D", u"\u0433", u"\u0448", u"\u0449", u"\u0437", u"\u0445", u"\u044A", u"\u00A7"], [u"LAST", u"\u0444", u"\u044B", u"\u0432", u"\u0430", u"\u043F", u"\u0440", u"\u043E", u"\u043B", u"\u0434", u"\u0436", u"\u044D", u"\\", u"ENTER"], [u"SHIFT", u"\u044F", u"\u0447", u"\u0441", u"\u043C", u"\u0438", u"\u0442", u"\u044C", u"\u0431", u"\u044E", u".", u"@", u"&", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE", u"<"] ], [ [u"\u0401", u"!", u"\"", u"\u2116", u";", u"%", u":", u"?", u"*", u"(", u")", u"_", u"+", u"BACKSPACE"], [u"FIRST", u"\u0419", u"\u0426", u"\u0423", u"\u041A", u"\u0415", u"\u041D", u"\u0413", u"\u0428", u"\u0429", u"\u0417", u"\u0425", u"\u042A", u"\u20BD"], [u"LAST", u"\u0424", u"\u042B", u"\u0412", u"\u0410", u"\u041F", u"\u0420", u"\u041E", u"\u041B", u"\u0414", u"\u0416", u"\u042D", u"/", u"ENTER"], [u"SHIFT", u"\u042F", u"\u0427", u"\u0421", u"\u041C", u"\u0418", u"\u0422", u"\u042C", u"\u0411", u"\u042E", u",", u"#", u"$", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE", u">"] ] ] self.scandinavian = [ [ [u"\u00A7", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"+", u"@", u"BACKSPACE"], [u"FIRST", u"q", u"w", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"\u00E5", u"[", u"]"], [u"LAST", u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"\u00F6", u"\u00E4", u"'", u"ENTER"], [u"SHIFT", u"<", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"\u00AB", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ], [ [u"\u00BD", u"!", u"\"", u"#", u"\u00A4", u"%", u"&", u"/", u"(", u")", u"=", u"?", u"|", u"BACKSPACE"], [u"FIRST", u"Q", u"W", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"\u00C5", u"{", u"}"], [u"LAST", u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"\u00D6", u"\u00C4", u"*", u"ENTER"], [u"SHIFT", u">", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"\u00BB", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ], [ [u"", u"\u00E2", u"\u00EA", u"\u00EE", u"\u00F4", u"\u00FB", u"\u00E4", u"\u00EB", u"\u00EF", u"\u00F6", u"\u00FC", u"\u00E3", u"\u00F5", u"BACKSPACE"], [u"FIRST", u"\u00E0", u"\u00E8", u"\u00EC", u"\u00F2", u"\u00F9", u"\u00E1", u"\u00E9", u"\u00ED", u"\u00F3", u"\u00FA", u"", u"", u""], [u"LAST", u"\u00C2", u"\u00CA", u"\u00CE", u"\u00D4", u"\u00DB", u"\u00C4", u"\u00CB", u"\u00CF", u"\u00D6", u"\u00DC", u"\u00C3", u"\u00D5", u"ENTER"], [u"SHIFT", u"\u00C0", u"\u00C8", u"\u00CC", u"\u00D2", u"\u00D9", u"\u00C1", u"\u00C9", u"\u00CD", u"\u00D3", u"\u00DA", u"", u"", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ] ] self.spanish = [ [ [u"\\", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"'", u"\u00A1", u"BACKSPACE"], [u"FIRST", u"q", u"w", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"@", u"+", u"\u00E7"], [u"LAST", u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"\u00F1", u"[", u"]", u"ENTER"], [u"SHIFT", u"<", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"\u20AC", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE", u"", u"\u00E1", u"\u00E9", u"\u00ED", u"\u00F3", u"\u00FA", u"\u00FC"] ], [ [u"|", u"!", u"\"", u"\u00B7", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"?", u"\u00BF", u"BACKSPACE"], [u"FIRST", u"Q", u"W", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"#", u"*", u"\u00C7"], [u"LAST", u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"\u00D1", u"{", u"}", u"ENTER"], [u"SHIFT", u">", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"\u00AC", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE", u"", u"\u00C1", u"\u00C9", u"\u00CD", u"\u00D3", u"\u00DA", u"\u00DC"] ] ] self.locales = { "ar_BH": [_("Arabic"), _("Bahrain"), self.arabic(self.english)], "ar_EG": [_("Arabic"), _("Egypt"), self.arabic(self.english)], "ar_JO": [_("Arabic"), _("Jordan"), self.arabic(self.english)], "ar_KW": [_("Arabic"), _("Kuwait"), self.arabic(self.english)], "ar_LB": [_("Arabic"), _("Lebanon"), self.arabic(self.english)], "ar_OM": [_("Arabic"), _("Oman"), self.arabic(self.english)], "ar_QA": [_("Arabic"), _("Qatar"), self.arabic(self.english)], "ar_SA": [_("Arabic"), _("Saudi Arabia"), self.arabic(self.english)], "ar_SY": [_("Arabic"), _("Syrian Arab Republic"), self.arabic(self.english)], "ar_AE": [_("Arabic"), _("United Arab Emirates"), self.arabic(self.english)], "ar_YE": [_("Arabic"), _("Yemen"), self.arabic(self.english)], "cs_CZ": [_("Czech"), _("Czechia"), [ [ [u";", u"+", u"\u011B", u"\u0161", u"\u010D", u"\u0159", u"\u017E", u"\u00FD", u"\u00E1", u"\u00ED", u"\u00E9", u"=", u"", u"BACKSPACE"], [u"FIRST", u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"\u00FA", u")", u""], [u"LAST", u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"\u016F", u"\u00A7", u"", u"ENTER"], [u"SHIFT", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"\u0148", u"", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ], [ [u"", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"%", u"", u"BACKSPACE"], [u"FIRST", u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"/", u"(", u""], [u"LAST", u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"\"", u"!", u"'", u"ENTER"], [u"SHIFT", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u"?", u":", u"_", u"\u0147", u"", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ], [ [u"", u"~", u"\u011A", u"\u0160", u"\u010C", u"\u0158", u"\u017D", u"\u00DD", u"\u00C1", u"\u00CD", u"\u00C9", u"`", u"", u"BACKSPACE"], [u"FIRST", u"\\", u"|", u"\u20AC", u"\u0165", u"\u0164", u"", u"", u"", u"\u00F3", u"\u00D3", u"\u00DA", u"\u00F7", u"\u00D7"], [u"LAST", u"", u"\u0111", u"\u00D0", u"[", u"]", u"\u010F", u"\u010E", u"\u0142", u"\u0141", u"\u016E", u"$", u"\u00DF", u"ENTER"], [u"SHIFT", u"", u"#", u"&", u"@", u"{", u"}", u"", u"<", u">", u"*", u"", u"\u00A4", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ] ]], "nl_NL": [_("Dutch"), _("Netherlands"), self.dutch(self.english)], "en_AU": [_("English"), _("Australian"), self.australian(self.english)], "en_GB": [_("English"), _("United Kingdom"), self.unitedKingdom(self.english)], "en_US": [_("English"), _("United States"), self.english], "en_EN": [_("English"), _("Various"), self.english], "et_EE": [_("Estonian"), _("Estonia"), self.estonian(self.scandinavian)], "fi_FI": [_("Finnish"), _("Finland"), self.finnish(self.scandinavian)], "fr_BE": [_("French"), _("Belgian"), self.belgian(self.french)], "fr_FR": [_("French"), _("France"), self.french], "de_DE": [_("German"), _("Germany"), self.german], "el_GR": [_("Greek (Modern)"), _("Greece"), [ [ [u"`", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"-", u"=", u"BACKSPACE"], [u"FIRST", u";", u"\u03C2", u"\u03B5", u"\u03C1", u"\u03C4", u"\u03C5", u"\u03B8", u"\u03B9", u"\u03BF", u"\u03C0", u"[", u"]", u"/"], [u"LAST", u"\u03B1", u"\u03C3", u"\u03B4", u"\u03C6", u"\u03B3", u"\u03B7", u"\u03BE", u"\u03BA", u"\u03BB", u"", u"'", u"\\", u"ENTER"], [u"SHIFT", u"<", u"\u03B6", u"\u03C7", u"\u03C8", u"\u03C9", u"\u03B2", u"\u03BD", u"\u03BC", u",", ".", u"\u03CA", u"\u03CB", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE", u"\u03AC", u"\u03AD", u"\u03AE", u"\u03AF", u"\u03CC", u"\u03CD", u"\u03CE"] ], [ [u"~", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"*", u"(", u")", u"_", u"+", u"BACKSPACE"], [u"FIRST", u":", u"", u"\u0395", u"\u03A1", u"\u03A4", u"\u03A5", u"\u0398", u"\u0399", u"\u039F", u"\u03A0", u"{", u"}", u"?"], [u"LAST", u"\u0391", u"\u03A3", u"\u0394", u"\u03A6", u"\u0393", u"\u0397", u"\u039E", u"\u039A", u"\u039B", u"", u"\"", u"|", u"ENTER"], [u"SHIFT", u">", u"\u0396", u"\u03A7", u"\u03A8", u"\u03A9", u"\u0392", u"\u039D", u"\u039C", u"<", u">", u"\u03AA", u"\u03AB", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE", u"\u0386", u"\u0388", u"\u0389", u"\u038A", u"\u038C", u"\u038E", u"\u038F"] ], [ [u"", u"", u"\u00B2", u"\u00B3", u"\u00A3", u"\u00A7", u"\u00B6", u"\u20AC", u"\u00A4", u"\u00A6", u"\u00B0", u"\u00B1", u"\u00BD", u"BACKSPACE"], [u"FIRST", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"", u""], [u"LAST", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"ENTER"], [u"SHIFT", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ] ]], "lv_LV": [_("Latvian"), _("Latvia"), self.latvian(self.english)], "lt_LT": [_("Lithuanian"), _("Lithuania"), self.lithuanian(self.english)], "nb_NO": [_("Norwegian"), _("Norway"), self.norwegian(self.scandinavian)], "fa_IR": [_("Persian"), _("Iran, Islamic Republic"), self.persian(self.english)], "pl_PL": [_("Polish"), _("Poland"), self.polish(self.english)], "ru_RU": [_("Russian"), _("Russian Federation"), self.russian], "sk_SK": [_("Slovak"), _("Slovakia"), [ [ [u"~", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"*", u"(", u")", u"\u00E1", u"\u00E4", u"BACKSPACE"], [u"FIRST", u"q", u"w", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"\u010D", u"\u010F", u"\u00E9"], [u"LAST", u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"\u00ED", u"\u013A", u"\u013E", u"ENTER"], [u"SHIFT", u"<", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"\u0148", u"\u00F3", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE", u"\u00F4", u"\u0155", u"\u0161", u"\u0165", u"\u00FA", u"\u00FD", u"\u017E"] ], [ [u"`", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"\u00C1", u"\u00C4", u"BACKSPACE"], [u"FIRST", u"Q", u"W", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"\u010C", u"\u010E", u"\u00C9"], [u"LAST", u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"\u00CD", u"\u0139", u"\u013D", u"ENTER"], [u"SHIFT", u">", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u"?", u":", u"\u0147", u"\u00D3", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE", u"\u00D4", u"\u0154", u"\u0160", u"\u0164", u"\u00DA", u"\u00DD", u"\u017D"] ], [ [u"", u"", u"\u00A7", u"\u00B0", u"\u00A4", u"\u20AC", u"\u00DF", u"\u0111", u"\u0110", u"\u0142", u"\u0141", u"", u"", u"BACKSPACE"], [u"FIRST", u"", u"", u"'", u"\"", u"+", u"-", u"\u00D7", u"\u00F7", u"=", u"_", u"~", u"", u""], [u"LAST", u"", u"", u"/", u"\\", u";", u"[", u"]", u"{", u"}", u"|", u"", u"", u"ENTER"], [u"SHIFT", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ] ]], "es_ES": [_("Spanish"), _("Spain"), self.spanish], "sv_SE": [_("Swedish"), _("Sweden"), self.swedish(self.scandinavian)], "th_TH": [_("Thai"), _("Thailand"), [ [ [u"", u"", u"\u0E45", u"\u0E20", u"\u0E16", u"\u0E38", u"\u0E36", u"\u0E04", u"\u0E15", u"\u0E08", u"\u0E02", u"\u0E0A", u"", u"BACKSPACE"], [u"FIRST", u"\u0E46", u"\u0E44", u"\u0E33", u"\u0E1E", u"\u0E30", u"\u0E31", u"\u0E35", u"\u0E23", u"\u0E19", u"\u0E22", u"\u0E1A", u"\u0E25", u""], [u"LAST", u"\u0E1F", u"\u0E2B", u"\u0E01", u"\u0E14", u"\u0E40", u"\u0E49", u"\u0E48", u"\u0E32", u"\u0E2A", u"\u0E27", u"\u0E07", u"\u0E03", u"OK"], [u"SHIFT", u"\u0E1C", u"\u0E1B", u"\u0E41", u"\u0E2D", u"\u0E34", u"\u0E37", u"\u0E17", u"\u0E21", u"\u0E43", u"\u0E1D", u"", u"", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ], [ [u"", u"", u"\u0E51", u"\u0E52", u"\u0E53", u"\u0E54", u"\u0E39", u"\u0E55", u"\u0E56", u"\u0E57", u"\u0E58", u"\u0E59", u"", u"BACKSPACE"], [u"FIRST", u"\u0E50", u"", u"\u0E0E", u"\u0E11", u"\u0E18", u"\u0E4D", u"\u0E4A", u"\u0E13", u"\u0E2F", u"\u0E0D", u"\u0E10", u"\u0E05", u""], [u"LAST", u"\u0E24", u"\u0E06", u"\u0E0F", u"\u0E42", u"\u0E0C", u"\u0E47", u"\u0E4B", u"\u0E29", u"\u0E28", u"\u0E0B", u"", u"\u0E3F", u"OK"], [u"SHIFT", u"", u"", u"\u0E09", u"\u0E2E", u"\u0E3A", u"\u0E4C", u"", u"\u0E12", u"\u0E2C", u"\u0E26", u"", u"", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ] ]], "uk_UA": [_("Ukrainian"), _("Ukraine"), self.ukranian(self.russian)] } self["actions"] = HelpableNumberActionMap(self, "VirtualKeyBoardActions", { "cancel": (self.cancel, _("Cancel any text changes and exit")), "save": (self.save, _("Save any text changes and exit")), "locale": (self.localeMenu, _("Select the virtual keyboard locale from a menu")), "shift": (self.shiftClicked, _("Select the virtual keyboard shifted character set")), "select": (self.processSelect, _("Select the character or action under the virtual keyboard cursor")), "up": (self.up, _("Move the virtual keyboard cursor up")), "left": (self.left, _("Move the virtual keyboard cursor left")), "right": (self.right, _("Move the virtual keyboard cursor right")), "down": (self.down, _("Move the virtual keyboard cursor down")), "first": (self.cursorFirst, _("Move the text buffer cursor to the first character")), "prev": (self.cursorLeft, _("Move the text buffer cursor left")), "next": (self.cursorRight, _("Move the text buffer cursor right")), "last": (self.cursorLast, _("Move the text buffer cursor to the last character")), "toggleOverwrite": (self.keyToggleOW, _("Toggle new text inserts before or overwrites existing text")), "backspace": (self.backClicked, _("Delete the character to the left of text buffer cursor")), "delete": (self.forwardClicked, _("Delete the character under the text buffer cursor")), "1": (self.keyNumberGlobal, _("Number or SMS style data entry")), "2": (self.keyNumberGlobal, _("Number or SMS style data entry")), "3": (self.keyNumberGlobal, _("Number or SMS style data entry")), "4": (self.keyNumberGlobal, _("Number or SMS style data entry")), "5": (self.keyNumberGlobal, _("Number or SMS style data entry")), "6": (self.keyNumberGlobal, _("Number or SMS style data entry")), "7": (self.keyNumberGlobal, _("Number or SMS style data entry")), "8": (self.keyNumberGlobal, _("Number or SMS style data entry")), "9": (self.keyNumberGlobal, _("Number or SMS style data entry")), "0": (self.keyNumberGlobal, _("Number or SMS style data entry")), "gotAsciiCode": (self.keyGotAscii, _("Keyboard data entry")) }, -2, description=_("Virtual KeyBoard Functions")) self.lang = language.getLanguage() self["prompt"] = Label(prompt) self["text"] = Input(text=text, maxSize=maxSize, visible_width=visible_width, type=type, currPos=len(text.decode("utf-8", "ignore")), allMarked=allMarked) self["list"] = VirtualKeyBoardList([]) self["mode"] = Label(_("INS")) self["locale"] = Label(_("Locale") + ": " + self.lang) self["language"] = Label(_("Language") + ": " + self.lang) self["key_info"] = StaticText(_("INFO")) self["key_red"] = StaticText(_("Exit")) self["key_green"] = StaticText(_("Save")) self["key_yellow"] = StaticText(_("Select locale")) self["key_blue"] = StaticText(self.shiftMsgs[1]) self["key_help"] = StaticText(_("HELP")) width, self.height = skin.parameters.get("VirtualKeyBoard", (45, 45)) self.width = self.key_bg and self.key_bg.size().width() or width self.shiftColors = skin.parameters.get("VirtualKeyBoardShiftColors", (0x00ffffff, 0x00ffffff, 0x0000ffff, 0x00ff00ff)) # Ensure there is a color for each shift level! self.language = None self.location = None self.keyList = [] self.shiftLevels = 0 self.shiftLevel = 0 self.keyboardWidth = 0 self.keyboardHeight = 0 self.maxKey = 0 self.overwrite = False self.selectedKey = None self.sms = NumericalTextInput(self.smsGotChar) self.smsChar = None self.setLocale() self.onExecBegin.append(self.setKeyboardModeAscii) self.onLayoutFinish.append(self.buildVirtualKeyBoard) def arabic(self, base): keyList = copy.deepcopy(base) keyList[1][0][8] = u"\u066D" keyList.extend([[ [u"\u0630", u"\u0661", u"\u0662", u"\u0663", u"\u0664", u"\u0665", u"\u0666", u"\u0667", u"\u0668", u"\u0669", u"\u0660", u"-", u"=", u"BACKSPACE"], [u"FIRST", u"\u0636", u"\u0635", u"\u062B", u"\u0642", u"\u0641", u"\u063A", u"\u0639", u"\u0647", u"\u062E", u"\u062D", u"\u062C", u"\u062F", u"\\"], [u"LAST", u"\u0634", u"\u0633", u"\u064A", u"\u0628", u"\u0644", u"\u0627", u"\u062A", u"\u0646", u"\u0645", u"\u0643", u"\u0637", u"", u"ENTER"], [u"SHIFT", u"\u0626", u"\u0621", u"\u0624", u"\u0631", u"\uFEFB", u"\u0649", u"\u0629", u"\u0648", u"\u0632", u"\u0638", u"", u"", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ], [ [u"\u0651", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"\u066D", u"(", u")", u"_", u"+", u"BACKSPACE"], [u"FIRST", u"\u0636", u"\u0635", u"\u062B", u"\u0642", u"\u0641", u"\u063A", u"\u0639", u"\u00F7", u"\u00D7", u"\u061B", u">", u"<", u"|"], [u"LAST", u"\u0634", u"\u0633", u"\u064A", u"\u0628", u"\u0644", u"\u0623", u"\u0640", u"\u060C", u"/", u":", u"\"", u"", u"ENTER"], [u"SHIFT", u"\u0626", u"\u0621", u"\u0624", u"\u0631", u"\uFEF5", u"\u0622", u"\u0629", u",", u".", u"\u061F", u"", u"", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ]]) return keyList def australian(self, base): keyList = copy.deepcopy(base) keyList[0][-1].extend([u"www.", u".com", u".net", u".org", u".edu", u".au", u".tv"]) keyList[1][-1].extend([u"www.", u".com", u".net", u".org", u".edu", u".au", u".tv"]) return keyList def belgian(self, base): keyList = copy.deepcopy(base) keyList[0][0][6] = u"\u00A7" keyList[0][0][8] = u"!" keyList[0][0][12] = u"-" keyList[0][2][12] = u"\u00B5" keyList[0][3][11] = u"=" keyList[1][0][0] = u"\u00B3" keyList[1][0][12] = u"_" keyList[1][1][11] = u"*" keyList[1][2][12] = u"\u00A3" keyList[1][3][11] = u"+" return keyList def dutch(self, base): keyList = copy.deepcopy(base) keyList[0][0][0] = u"@" keyList[0][0][11] = u"/" keyList[0][0][12] = u"\u00BA" keyList[0][1][11] = u"\u00A8" keyList[0][1][12] = u"*" keyList[0][1][13] = u"<" keyList[0][2][10] = u"+" keyList[0][2][11] = u"\u00B4" keyList[0][2][12] = u"\\" keyList[0][3] = [u"SHIFT", u"]", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", u".", u"-", u"{", u"SHIFT"] keyList[0][-1].extend([u"www.", u".com", u".net", u".org", u".edu", u".nl", u".tv"]) keyList[1][0] = [u"\u00A7", u"!", u"\"", u"#", u"$", u"%", u"&", u"_", u"(", u")", u"'", u"?", u"~", u"BACKSPACE"] keyList[1][1][11] = u"^" keyList[1][1][12] = u"|" keyList[1][1][13] = u">" keyList[1][2][10] = u"\u00B1" keyList[1][2][11] = u"`" keyList[1][2][12] = u"\u00A6" keyList[1][3] = [u"SHIFT", u"[", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"=", u"}", u"SHIFT"] keyList[1][-1].extend([u"www.", u".com", u".net", u".org", u".edu", u".nl", u".tv"]) keyList.append([ [u"\u00AC", u"\u00B9", u"\u00B2", u"\u00B3", u"\u00BC", u"\u00BD", u"\u00BE", u"\u00A3", u"{", u"}", u"$", u"\\", u"", u"BACKSPACE"], [u"FIRST", u"", u"", u"\u20AC", u"\u00B6", u"", u"", u"", u"", u"", u"", u"", u"", u""], [u"LAST", u"", u"\u00E1", u"\u00E9", u"\u00ED", u"\u00F3", u"\u00FA", u"\u00C1", u"\u00C9", u"\u00CD", u"\u00D3", u"\u00DA", u"", u"ENTER"], [u"SHIFT", u"\u00A6", u"\u00AB", u"\u00BB", u"\u00A2", u"", u"", u"", u"\u00B5", u"", u"\u00B7", u"", u"", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ]) return keyList def estonian(self, base): keyList = copy.deepcopy(base) keyList[0][1][11] = u"\u00FC" keyList[0][1][12] = u"\u00F5" keyList[0][1][13] = u"\u0161" keyList[0][3][12] = u"\u017E" keyList[0][4].extend([u"[", u"]", u"\\"]) keyList[1][1][11] = u"\u00DC" keyList[1][1][12] = u"\u00D5" keyList[1][1][13] = u"\u0160" keyList[1][3][12] = u"\u017D" keyList[1][4].extend([u"{", u"}", u"\u00A3", u"$", u"\u20AC"]) del keyList[2] return keyList def finnish(self, base): keyList = copy.deepcopy(base) keyList[0][4].append(u"\\") keyList[1][4].extend([u"\u00A3", u"$", u"\u20AC"]) return keyList def latvian(self, base): keyList = copy.deepcopy(base) keyList.append([ [u"", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"", u"BACKSPACE"], [u"FIRST", u"", u"\u0113", u"\u0112", u"\u0157", u"\u0156", u"\u016B", u"\u016A", u"\u012B", u"\u012A", u"\u014D", u"\u014C", u"", u""], [u"LAST", u"\u0101", u"\u0100", u"\u0161", u"\u0160", u"\u0123", u"\u0122", u"\u0137", u"\u0136", u"\u013C", u"\u013B", u"", u"", u"ENTER"], [u"SHIFT", u"\u017E", u"\u017D", u"\u010D", u"\u010C", u"", u"\u0146", u"\u0145", u"", u"", u"", u"", u"", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ]) return keyList def lithuanian(self, base): keyList = copy.deepcopy(base) keyList[0][0] = [u"`", u"\u0105", u"\u010D", u"\u0119", u"\u0117", u"\u012F", u"\u0161", u"\u0173", u"\u016B", u"", u"", u"", u"\u017E", u"BACKSPACE"] keyList[0][1][13] = u"" keyList[0][2][12] = u"\\" keyList[1][0] = [u"~", u"\u0104", u"\u010C", u"\u0118", u"\u0116", u"\u012E", u"\u0160", u"\u0172", u"\u016A", u"\u201E", u"\u201C", u"", u"\u017D", u"BACKSPACE"] keyList[1][1][13] = u"" keyList[1][2][12] = u"|" keyList.append([ [u"\u02DC", u"\u00BC", u"\u00BD", u"\u00BE", u"\u00A4", u"\u00A2", u"\u00B0", u"\u00A7", u"\u00D7", u"\u00AB", u"\u00BB", u"\u00F7", u"\u00B1", u"BACKSPACE"], [u"FIRST", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"-", u"=", u"\u00AD"], [u"LAST", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"*", u"(", u")", u"_", u"+", u"ENTER"], [u"SHIFT", u"", u"\u00DF", u"\u00A9", u"\u00AE", u"\u2122", u"\u00AC", u"\u00A3", u"\u20AC", u"\u00B7", u"\u00B9", u"\u00B2", u"\u00B3", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ]) return keyList def norwegian(self, base): keyList = copy.deepcopy(base) keyList[0][0][0] = u"|" keyList[0][0][12] = u"\\" keyList[0][2][10] = u"\u00F8" keyList[0][2][11] = u"\u00E6" keyList[0][3][12] = u"\u00B5" keyList[1][0][0] = u"\u00A7" keyList[1][0][12] = u"@" keyList[1][2][10] = u"\u00D8" keyList[1][2][11] = u"\u00C6" keyList[1][3][12] = u"" keyList[1][4].extend([u"\u00A3", u"$", u"\u20AC"]) return keyList def persian(self, base): keyList = copy.deepcopy(base) keyList.append([ [u"\u00F7", u"\u06F1", u"\u06F2", u"\u06F3", u"\u06F4", u"\u06F5", u"\u06F6", u"\u06F7", u"\u06F8", u"\u06F9", u"\u06F0", u"-", u"=", u"BACKSPACE"], [u"FIRST", u"\u0636", u"\u0635", u"\u062B", u"\u0642", u"\u0641", u"\u063A", u"\u0639", u"\u0647", u"\u062E", u"\u062D", u"\u062C", u"\u0686", u"\u067E"], [u"LAST", u"\u0634", u"\u0633", u"\u0649", u"\u0628", u"\u0644", u"\u0622", u"\u0627", u"\u062A", u"\u0646", u"\u0645", u"\u06A9", u"\u06AF", u"ENTER"], [u"SHIFT", u"\u0638", u"\u0637", u"\u0698", u"\u0632", u"\u0631", u"\u0630", u"\u062F", u"\u0626", u"\u0621", u"\u0648", u"\u060C", u"\u061F", u"SHIFT"], [u"EXIT", u"LOC", u"LEFT", u"RIGHT", u"ALL", u"CLR", u"SPACE"] ]) return keyList def polish(self, base): keyList = copy.deepcopy(base) keyList[0][3][11] = u"\u0105" keyList[0][3][12] = u"\u0107" keyList[0][-1].extend([u"\u0119", u"\u0142", u"\u0144", u"\u00F3", u"\u015B", u"\u017A", u"\u017C"]) keyList[1][2][12] = u"\u20AC" keyList[1][3][11] = u"\u0104" keyList[1][3][12] = u"\u0106" keyList[1][-1].extend([u"\u0118", u"\u0141", u"\u0143", u"\u00D3", u"\u015A", u"\u0179", u"\u017B"]) return keyList def swedish(self, base): keyList = copy.deepcopy(base) keyList[0][4].extend([u"\\", u"\u00B5"]) keyList[1][4].extend([u"\u00A3", u"$", u"\u20AC"]) return keyList def ukranian(self, base): keyList = copy.deepcopy(base) keyList[0][1][12] = u"\u0457" keyList[0][2][2] = u"\u0456" keyList[0][2][11] = u"\u0454" keyList[0][3][11] = u"\u0491" keyList[0][4].append(u"@") keyList[1][1][12] = u"\u0407" keyList[1][2][2] = u"\u0406" keyList[1][2][11] = u"\u0404" keyList[1][3][11] = u"\u0490" keyList[1][4].append(u"#") return keyList def unitedKingdom(self, base): keyList = copy.deepcopy(base) keyList[0][1][13] = u"\u00A6" keyList[0][2][12] = u"#" keyList[0][3] = [u"SHIFT", u"\\", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", u".", u"/", u"", u"SHIFT"] # keyList[0][-1].extend([u"\u00E1", u"\u00E9", u"\u00ED", u"\u00F3", u"\u00FA"]) # English users don't use the accented characters. keyList[1][0][0] = u"\u00AC" keyList[1][0][2] = u"\"" keyList[1][0][3] = u"\u00A3" keyList[1][1][13] = u"\u20AC" keyList[1][2][11] = u"@" keyList[1][2][12] = u"~" keyList[1][3] = [u"SHIFT", u"|", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u"<", u">", u"?", u"", u"SHIFT"] # keyList[1][-1].extend([u"\u00C1", u"\u00C9", u"\u00CD", u"\u00D3", u"\u00DA"]) # English users don't use the accented characters. return keyList def smsGotChar(self): if self.smsChar and self.selectAsciiKey(self.smsChar): self.processSelect() def setLocale(self): self.language, self.location, self.keyList = self.locales.get(self.lang, [None, None, None]) if self.language is None or self.location is None or self.keyList is None: self.lang = "en_EN" self.language = _("English") self.location = _("Various") self.keyList = self.english self.shiftLevel = 0 self["locale"].setText(_("Locale") + ": " + self.lang + " (" + self.language + " - " + self.location + ")") def buildVirtualKeyBoard(self): self.shiftLevels = len(self.keyList) if self.shiftLevel >= self.shiftLevels: self.shiftLevel = 0 self.keyboardWidth = len(self.keyList[self.shiftLevel][0]) self.keyboardHeight = len(self.keyList[self.shiftLevel]) self.maxKey = self.keyboardWidth * (self.keyboardHeight - 1) + len(self.keyList[self.shiftLevel][-1]) - 1 # print "[VirtualKeyBoard] DEBUG: Width=%d, Height=%d, Keys=%d, maxKey=%d, shiftLevels=%d" % (self.keyboardWidth, self.keyboardHeight, self.maxKey + 1, self.maxKey, self.shiftLevels) self.list = [] for keys in self.keyList[self.shiftLevel]: self.list.append(self.virtualKeyBoardEntryComponent(keys)) self.previousSelectedKey = None if self.selectedKey is None: self.selectedKey = self.keyboardWidth self.markSelectedKey() def virtualKeyBoardEntryComponent(self, keys): res = [keys] text = [] offset = 14 - self.keyboardWidth # 14 represents the maximum buttons per row as defined here and in the skin (14 x self.width). x = self.width * offset / 2 if offset % 2: x += self.width / 2 for key in keys: image = self.keyImages[self.shiftLevel].get(key, None) if image: width = image.size().width() res.append(MultiContentEntryPixmapAlphaBlend(pos=(x, 0), size=(width, self.height), png=image)) else: width = self.width res.append(MultiContentEntryPixmapAlphaBlend(pos=(x, 0), size=(width, self.height), png=self.keyBackgrounds.get(key, self.key_bg))) if len(key) > 1: # NOTE: UTF8 / Unicode glyphs only count as one character here. text.append(MultiContentEntryText(pos=(x, 0), size=(width, self.height), font=1, flags=RT_HALIGN_CENTER | RT_VALIGN_CENTER, text=_(key.encode("utf-8")), color=self.shiftColors[self.shiftLevel])) else: text.append(MultiContentEntryText(pos=(x, 0), size=(width, self.height), font=0, flags=RT_HALIGN_CENTER | RT_VALIGN_CENTER, text=key.encode("utf-8"), color=self.shiftColors[self.shiftLevel])) x += width return res + text def markSelectedKey(self): if self.previousSelectedKey is not None: self.list[self.previousSelectedKey / self.keyboardWidth] = self.list[self.previousSelectedKey / self.keyboardWidth][:-1] if self.selectedKey > self.maxKey: self.selectedKey = self.maxKey x = self.list[self.selectedKey / self.keyboardWidth][self.selectedKey % self.keyboardWidth + 1][1] if self.key_sel is None: width = self.width else: width = self.key_sel.size().width() self.list[self.selectedKey / self.keyboardWidth].append(MultiContentEntryPixmapAlphaBlend(pos=(x, 0), size=(width, self.height), png=self.key_sel)) self.previousSelectedKey = self.selectedKey self["list"].setList(self.list) def okClicked(self): # Deprecated legacy interface to new processSelect used by YouTubeVirtualKeyBoard self.processSelect() def processSelect(self): self.smsChar = None text = self.keyList[self.shiftLevel][self.selectedKey / self.keyboardWidth][self.selectedKey % self.keyboardWidth].encode("UTF-8") if text == u"": pass elif text == u"ALL": self["text"].markAll() elif text == u"BACK": self["text"].deleteBackward() elif text == u"BACKSPACE": self["text"].deleteBackward() elif text == u"BLANK": pass elif text == u"CLR": self["text"].deleteAllChars() self["text"].update() elif text == u"ENTER": self.save() elif text == u"ESC": self.cancel() elif text == u"EXIT": self.cancel() elif text == u"FIRST": self["text"].home() elif text == u"LOC": self.localeMenu() elif text == u"LAST": self["text"].end() elif text == u"LEFT": self["text"].left() elif text == u"OK": self.save() elif text == u"RIGHT": self["text"].right() elif text == u"SAVE": self.save() elif text == u"SHIFT": self.shiftClicked() elif text == u"Shift": self.shiftClicked() elif text == u"SPACE": self["text"].char(" ".encode("UTF-8")) else: self["text"].char(text.encode("UTF-8")) def cancel(self): self.close(None) def save(self): self.close(self["text"].getText()) def localeMenu(self): languages = [] for locale, data in self.locales.iteritems(): languages.append((data[0] + " - " + data[1] + " (" + locale + ")", locale)) languages = sorted(languages) index = 0 default = 0 for item in languages: if item[1] == self.lang: default = index break index += 1 self.session.openWithCallback(self.localeMenuCallback, ChoiceBox, _("Available locales are:"), list=languages, selection=default, keys=[]) def localeMenuCallback(self, choice): if choice: self.lang = choice[1] self.setLocale() self.buildVirtualKeyBoard() def shiftClicked(self): self.smsChar = None self.shiftLevel = (self.shiftLevel + 1) % self.shiftLevels nextLevel = (self.shiftLevel + 1) % self.shiftLevels self["key_blue"].setText(self.shiftMsgs[nextLevel]) self.buildVirtualKeyBoard() def keyToggleOW(self): self["text"].toggleOverwrite() self.overwrite = not self.overwrite if self.overwrite: self["mode"].setText(_("OVR")) else: self["mode"].setText(_("INS")) def backClicked(self): self["text"].deleteBackward() def forwardClicked(self): self["text"].deleteForward() def cursorFirst(self): self["text"].home() def cursorLeft(self): self["text"].left() def cursorRight(self): self["text"].right() def cursorLast(self): self["text"].end() def up(self): self.smsChar = None self.selectedKey -= self.keyboardWidth if self.selectedKey < 0: self.selectedKey = self.maxKey / self.keyboardWidth * self.keyboardWidth + self.selectedKey % self.keyboardWidth if self.selectedKey > self.maxKey: self.selectedKey -= self.keyboardWidth self.markSelectedKey() def left(self): self.smsChar = None self.selectedKey = self.selectedKey / self.keyboardWidth * self.keyboardWidth + (self.selectedKey + self.keyboardWidth - 1) % self.keyboardWidth if self.selectedKey > self.maxKey: self.selectedKey = self.maxKey self.markSelectedKey() def right(self): self.smsChar = None self.selectedKey = self.selectedKey / self.keyboardWidth * self.keyboardWidth + (self.selectedKey + 1) % self.keyboardWidth if self.selectedKey > self.maxKey: self.selectedKey = self.selectedKey / self.keyboardWidth * self.keyboardWidth self.markSelectedKey() def down(self): self.smsChar = None self.selectedKey += self.keyboardWidth if self.selectedKey > self.maxKey: self.selectedKey %= self.keyboardWidth self.markSelectedKey() def keyNumberGlobal(self, number): self.smsChar = self.sms.getKey(number) self.selectAsciiKey(self.smsChar) def keyGotAscii(self): self.smsChar = None if self.selectAsciiKey(str(unichr(getPrevAsciiCode()).encode("utf-8"))): self.processSelect() def selectAsciiKey(self, char): if char == u" ": char = u"SPACE" self.shiftLevel = -1 for keyList in (self.keyList): self.shiftLevel = (self.shiftLevel + 1) % self.shiftLevels self.buildVirtualKeyBoard() selkey = 0 for keys in keyList: for key in keys: if key == char: self.selectedKey = selkey self.markSelectedKey() return True selkey += 1 return False
class ServiceList(HTMLComponent, GUIComponent): MODE_NORMAL = 0 MODE_FAVOURITES = 1 def __init__(self, session = None): GUIComponent.__init__(self) self.session = session self.picFolder = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/folder.png")) self.picMarker = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/marker.png")) self.picDVB_S = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "ico_dvb_s-fs8.png")) self.picDVB_C = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "ico_dvb_c-fs8.png")) self.picDVB_T = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "ico_dvb_t-fs8.png")) self.picServiceGroup = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "ico_service_group-fs8.png")) self.markedForeground = 0xffffff self.markedBackground = 0xff0000 self.markedForegroundSelected = 0xffffff self.markedBackgroundSelected = 0x800000 colors = TemplatedColors().colors if "ListboxMarkedForeground" in colors: self.markedForeground = colors["ListboxMarkedForeground"] if "ListboxMarkedBackground" in colors: self.markedBackground = colors["ListboxMarkedBackground"] if "ListboxMarkedAndSelectedForeground" in colors: self.markedForegroundSelected = colors["ListboxMarkedAndSelectedForeground"] if "ListboxMarkedAndSelectedBackground" in colors: self.markedBackgroundSelected = colors["ListboxMarkedAndSelectedBackground"] self.serviceNotAvail = 0xbbbbbb self.serviceEventProgressbarColor = None self.serviceEventProgressbarColorSelected = None self.serviceEventProgressbarBackColor = None self.serviceEventProgressbarBackColorSelected = None self.serviceEventProgressbarBorderColor = None self.serviceEventProgressbarBorderColorSelected = None self.serviceDescriptionColor = 0xe7b53f self.serviceDescriptionColorSelected = 0xe7b53f self.recordingColor = 0xff4A3C self.recordingColorSelected = 0xff4A3C self.additionalInfoColor = None self.additionalInfoColorSelected = None self.picServiceEventProgressbar = None self.selectionPixmapStandard = None self.selectionPixmapBig = None self.l = eListboxServiceContent() self.l.setBuildFunc(self.buildOptionEntry, True) self.l.setFont(0, gFont("Regular", 18)) # AdditionalInfoFont self.l.setFont(1, gFont("Regular", 20)) # ServiceNumberFont self.l.setFont(2, gFont("Regular", 22)) # ServiceNameFont self.l.setFont(3, gFont("Regular", 18)) # ServiceInfoFont self.serviceNameFont = gFont("Regular", 22) self.serviceInfoFontHeight = 18 self.additionalInfoFont = gFont("Regular", 18) self.list = [] self.size = 0 self.service_center = eServiceCenter.getInstance() self.numberoffset = 0 self.is_playable_ignore = eServiceReference() self.root = None self.mode = self.MODE_NORMAL self.itemHeight = 28 self.l.setItemHeight(28) self.onSelectionChanged = [ ] self.recordingList = {} self.piconLoader = PiconLoader() if self.session: self.session.nav.RecordTimer.on_state_change.append(self.onTimerEntryStateChange) config.usage.configselection_showrecordings.addNotifier(self.getRecordingList, initial_call = True) config.usage.configselection_bigpicons.addNotifier(self.setItemHeight, initial_call = True) config.usage.configselection_secondlineinfo.addNotifier(self.setItemHeight, initial_call = False) def getRecordingList(self,configElement = None): self.recordingList = {} if config.usage.configselection_showrecordings.value: if NavigationInstance.instance.getRecordings(): for timer in NavigationInstance.instance.RecordTimer.timer_list: if timer.state == TimerEntry.StateRunning and not timer.justplay and hasattr(timer, "Filename"): self.recordingList[str(timer.service_ref)] = 1 def onTimerEntryStateChange(self,timer): if config.usage.configselection_showrecordings.value: if hasattr(timer, "Filename") and not timer.justplay and timer.state == TimerEntry.StateRunning: self.recordingList[str(timer.service_ref)] = 1 else: if self.recordingList.has_key(str(timer.service_ref)): del self.recordingList[str(timer.service_ref)] def setItemHeight(self, configElement = None): if (config.usage.configselection_bigpicons.value or config.usage.configselection_secondlineinfo.value != "0") and self.mode == self.MODE_FAVOURITES: self.l.setItemHeight(60) if self.instance is not None and self.selectionPixmapBig: self.instance.setSelectionPicture(self.selectionPixmapBig) else: self.l.setItemHeight(self.itemHeight) if self.instance is not None and self.selectionPixmapStandard: self.instance.setSelectionPicture(self.selectionPixmapStandard) def paintProgressBar(self, event, xoffset, width, height): percent = 0 progressW = 52 progressH = 8 if event: now = int(time()) percent = 100 * (now - event.getBeginTime()) / event.getDuration() top = int((height - progressH) / 2) if self.picServiceEventProgressbar is None: return(eListboxPythonMultiContent.TYPE_PROGRESS, xoffset, top, progressW, progressH, percent, 1, self.serviceEventProgressbarColor, self.serviceEventProgressbarColorSelected, self.serviceEventProgressbarBackColor, self.serviceEventProgressbarBackColorSelected) else: return(eListboxPythonMultiContent.TYPE_PROGRESS_PIXMAP, xoffset, top, progressW, progressH, percent, self.picServiceEventProgressbar, 1, self.serviceEventProgressbarBorderColor, self.serviceEventProgressbarBorderColorSelected, self.serviceEventProgressbarBackColor, self.serviceEventProgressbarBackColorSelected) def buildOptionEntry(self, service, **args): width = self.l.getItemSize().width() height = self.l.getItemSize().height() selected = args["selected"] res = [ None ] showListNumbers = config.usage.configselection_showlistnumbers.value showPicons = self.mode == self.MODE_FAVOURITES and config.usage.configselection_showpicons.value showServiceName = self.mode == self.MODE_NORMAL or (self.mode == self.MODE_FAVOURITES and config.usage.configselection_showservicename.value) showProgressbar = config.usage.show_event_progress_in_servicelist.value progressbarPosition = config.usage.configselection_progressbarposition.value servicenameWidth = config.usage.configselection_servicenamecolwidth.value columnStyle = config.usage.configselection_columnstyle.value additionalposition = config.usage.configselection_additionaltimedisplayposition.value bigPicons = self.mode == self.MODE_FAVOURITES and config.usage.configselection_bigpicons.value secondlineinfo = config.usage.configselection_secondlineinfo.value # get service information service_info = self.service_center.info(service) isMarker = service.flags & eServiceReference.isMarker isPlayable = not(service.flags & eServiceReference.isDirectory or isMarker) recording = False if config.usage.configselection_showrecordings.value: if self.recordingList.has_key(service.toString()): recording = True else: if isPlayable and len(self.recordingList) and service.flags & eServiceReference.mustDescent: alist = ServiceReference(service).list() while True: aservice = alist.getNext() if not aservice.valid(): break if self.recordingList.has_key(aservice.toString()): recording = True break marked = 0 if self.l.isCurrentMarked() and selected: marked = 2 elif self.l.isMarked(service): if selected: marked = 2 else: marked = 1 if marked == 1: # marked additionalInfoColor = serviceDescriptionColor = forgroundColor = self.markedForeground backgroundColor = self.markedBackground forgroundColorSel = backgroundColorSel = additionalInfoColorSelected = serviceDescriptionColorSelected = None elif marked == 2: # marked and selected additionalInfoColorSelected = serviceDescriptionColorSelected = forgroundColorSel = self.markedForegroundSelected backgroundColorSel = self.markedBackgroundSelected forgroundColor = additionalInfoColor = serviceDescriptionColor = backgroundColor = None else: if recording: forgroundColor = additionalInfoColor = serviceDescriptionColor = self.recordingColor forgroundColorSel = additionalInfoColorSelected = serviceDescriptionColorSelected = self.recordingColorSelected backgroundColor = backgroundColorSel = None else: forgroundColor = forgroundColorSel = backgroundColor = backgroundColorSel = None serviceDescriptionColor = self.serviceDescriptionColor serviceDescriptionColorSelected = self.serviceDescriptionColorSelected additionalInfoColor = self.additionalInfoColor additionalInfoColorSelected = self.additionalInfoColorSelected if (marked == 0 and isPlayable and service_info and self.is_playable_ignore.valid() and not service_info.isPlayable(service, self.is_playable_ignore)): forgroundColor = forgroundColorSel = additionalInfoColor = additionalInfoColorSelected = serviceDescriptionColor = serviceDescriptionColorSelected = self.serviceNotAvail # set windowstyle if marked > 0: res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 0, width , height, 1, RT_HALIGN_RIGHT, "", forgroundColor, forgroundColorSel, backgroundColor, backgroundColorSel)) info = self.service_center.info(service) serviceName = info.getName(service) or "<n/a>" event = info.getEvent(service) index = self.getCurrentIndex() xoffset = 2 pixmap = None drawProgressbar = isPlayable and showProgressbar if service.flags & eServiceReference.isMarker: pixmap = self.picMarker elif service.flags & eServiceReference.isGroup: pixmap = self.picServiceGroup elif service.flags & eServiceReference.isDirectory: pixmap = self.picFolder else: orbpos = service.getUnsignedData(4) >> 16; if orbpos == 0xFFFF: pixmap = self.picDVB_C elif orbpos == 0xEEEE: pixmap = self.picDVB_T else: pixmap = self.picDVB_S if pixmap is not None: pixmap_size = self.picMarker.size() ypos = (height - pixmap_size.height()) / 2 pix_width = pixmap_size.width() res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, xoffset, ypos, pix_width, height, pixmap)) xoffset += pix_width + 8 if self.mode != self.MODE_NORMAL: # servicenumber if not (service.flags & eServiceReference.isMarker) and showListNumbers: markers_before = self.l.getNumMarkersBeforeCurrent() text = "%d" % (self.numberoffset + index + 1 - markers_before) res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, 50 , height, 1, RT_HALIGN_RIGHT|RT_VALIGN_CENTER, text, forgroundColor, forgroundColorSel, backgroundColor, backgroundColorSel)) xoffset += 60 # picons if isPlayable and showPicons: if service.flags & eServiceReference.mustDescent: alist = ServiceReference(service).list() first_in_alternative = alist and alist.getNext() if first_in_alternative: service_str = first_in_alternative.toString() else: service_str = service.toString() else: service_str = service.toString() picon = self.piconLoader.getPicon(service_str) if picon: pixmap_size = picon.size() ypos = (height - pixmap_size.height()) / 2 pix_width = pixmap_size.width() res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, xoffset, ypos, pix_width, height, picon)) if bigPicons: xoffset += 108 else: xoffset += 58 # progressbar between servicenumber and servicename if drawProgressbar and progressbarPosition == "0": res.append(self.paintProgressBar(event, xoffset, width, height)) xoffset += 60 addtimedisplay = "" addtimedisplayWidth = 0 if config.usage.configselection_showadditionaltimedisplay.value != "0" and event and isPlayable: if columnStyle: self.textRenderer.setFont(self.additionalInfoFont) if config.usage.configselection_showadditionaltimedisplay.value == "1": # percent now = int(time()) percent = 100 * (now - event.getBeginTime()) / event.getDuration() addtimedisplay = "%d%%" % percent if columnStyle: self.textRenderer.setText("100%") elif config.usage.configselection_showadditionaltimedisplay.value == "2": # remain now = int(time()) remain = int((event.getBeginTime() + event.getDuration() - now) / 60) addtimedisplay = "+%d min" % remain if columnStyle: self.textRenderer.setText("+%d min" % 9999) elif config.usage.configselection_showadditionaltimedisplay.value == "3": # Remain / duration now = int(time()) remain = int((event.getBeginTime() + event.getDuration() - now) / 60) duration = int(event.getDuration() / 60) addtimedisplay = "+%d/%d min" % (remain, duration) if columnStyle: self.textRenderer.setText("+%d/%d min" % (9999, 9999)) elif config.usage.configselection_showadditionaltimedisplay.value == "4": # elapsed now = int(time()) elapsed = int((now - event.getBeginTime()) / 60) addtimedisplay = "%d min" % elapsed if columnStyle: self.textRenderer.setText("%d min" % 9999) elif config.usage.configselection_showadditionaltimedisplay.value == "5": # elapsed / duration now = int(time()) elapsed = int((now - event.getBeginTime()) / 60) duration = int(event.getDuration() / 60) addtimedisplay = "%d/%d min" % (elapsed, duration) if columnStyle: self.textRenderer.setText("%d/%d min" % (9999, 9999)) elif config.usage.configselection_showadditionaltimedisplay.value == "6": # elapsed / remain / duration now = int(time()) elapsed = int((now - event.getBeginTime()) / 60) remain = int((event.getBeginTime() + event.getDuration() - now) / 60) duration = int(event.getDuration() / 60) addtimedisplay = "%d/+%d/%d min" % (elapsed, remain, duration) if columnStyle: self.textRenderer.setText("%d/+%d/%d min" % (9999, 9999, 9999)) elif config.usage.configselection_showadditionaltimedisplay.value == "7": # begin - end time beginTime = localtime(event.getBeginTime()) endTime = localtime(event.getBeginTime()+event.getDuration()) addtimedisplay = "%02d:%02d - %02d:%02d" % (beginTime[3],beginTime[4],endTime[3],endTime[4]) if columnStyle: self.textRenderer.setText("00:00 - 00:000") if columnStyle: addtimedisplayWidth = self.textRenderer.calculateSize().width() if columnStyle: rwidth = 0 # servicename if (isPlayable and showServiceName) or not isPlayable: if isPlayable: rwidth = servicenameWidth # space for servicename else: rwidth = width - xoffset # space for servicename res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, rwidth , height, 2, RT_HALIGN_LEFT|RT_VALIGN_CENTER, serviceName, forgroundColor, forgroundColorSel, backgroundColor, backgroundColorSel)) xoffset = xoffset + rwidth + 10 # progressbar between servicename and service description if drawProgressbar and progressbarPosition == "1": res.append(self.paintProgressBar(event, xoffset, width, height)) xoffset += 60 if event and isPlayable: if addtimedisplay != "" and additionalposition == "1": if drawProgressbar and progressbarPosition == "2": rwidth = width - xoffset - addtimedisplayWidth rwidth -= 60 else: rwidth = width - xoffset - addtimedisplayWidth else: rwidth = width-xoffset if drawProgressbar and progressbarPosition == "2": rwidth -= 60 if addtimedisplay != "" and additionalposition == "0": # add time text before service description res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, addtimedisplayWidth, height, 0, RT_HALIGN_RIGHT|RT_VALIGN_CENTER, addtimedisplay, additionalInfoColor, additionalInfoColorSelected, backgroundColor, backgroundColorSel)) addoffset = addtimedisplayWidth + 10 xoffset += addoffset rwidth -= addoffset # service description if secondlineinfo != "0" and self.mode == self.MODE_FAVOURITES: res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, rwidth, self.serviceInfoFontHeight+6, 3, RT_HALIGN_LEFT|RT_VALIGN_CENTER, event.getEventName(), serviceDescriptionColor, serviceDescriptionColorSelected, backgroundColor, backgroundColorSel)) if secondlineinfo == "1": # shortdescription text = event.getShortDescription() else: event_next = eEPGCache.getInstance().lookupEventTime(service, -1, 1) if event_next: beginTime = localtime(event_next.getBeginTime()) endTime = localtime(event_next.getBeginTime()+event_next.getDuration()) text = "%02d:%02d - %02d:%02d %s" % (beginTime[3],beginTime[4],endTime[3],endTime[4], event_next.getEventName()) else: text = "%s: n/a" % _("upcoming event") res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, self.serviceInfoFontHeight+6, rwidth, height - (self.serviceInfoFontHeight+6), 0, RT_HALIGN_LEFT|RT_VALIGN_CENTER, text, additionalInfoColor, additionalInfoColorSelected, backgroundColor, backgroundColorSel)) else: res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, rwidth, height, 3, RT_HALIGN_LEFT|RT_VALIGN_CENTER, event.getEventName(), serviceDescriptionColor, serviceDescriptionColorSelected, backgroundColor, backgroundColorSel)) # progressbar after service description if drawProgressbar and progressbarPosition == "2": xoffset = xoffset + rwidth + 5 res.append(self.paintProgressBar(event, xoffset, width, height)) xoffset += 60 elif addtimedisplay != "": xoffset = xoffset + rwidth # add time text at last position if addtimedisplay != "" and additionalposition == "1": res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, width-xoffset , height, 0, RT_HALIGN_RIGHT|RT_VALIGN_CENTER, addtimedisplay, additionalInfoColor, additionalInfoColorSelected, backgroundColor, backgroundColorSel)) else: if event and isPlayable: self.textRenderer.setFont(self.serviceNameFont) self.textRenderer.setText(serviceName) length = self.textRenderer.calculateSize().width() + 10 res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, length , height, 2, RT_HALIGN_LEFT|RT_VALIGN_CENTER, serviceName, forgroundColor, forgroundColorSel, backgroundColor, backgroundColorSel)) xoffset += length if addtimedisplay != "": if additionalposition == "1": # add time text after service description text = "(%s %s)" % (event.getEventName(), addtimedisplay) else: # add time text before service description text = "(%s %s)" % (addtimedisplay, event.getEventName()) else: text = "(%s)" % (event.getEventName()) if drawProgressbar and progressbarPosition == "2": # progressbar after service description length = width-xoffset - 60 else: length = width-xoffset # service description res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, length , height, 3, RT_HALIGN_LEFT|RT_VALIGN_CENTER, text, serviceDescriptionColor, serviceDescriptionColorSelected, backgroundColor, backgroundColorSel)) if drawProgressbar and progressbarPosition == "2": xoffset += length + 5 res.append(self.paintProgressBar(event, xoffset, width, height)) else: res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, width - xoffset , height, 2, RT_HALIGN_LEFT|RT_VALIGN_CENTER, serviceName, forgroundColor, forgroundColorSel, backgroundColor, backgroundColorSel)) return res def applySkin(self, desktop, parent): attribs = [ ] for (attrib, value) in self.skinAttributes: if attrib == "foregroundColorMarked": self.markedForeground = parseColor(value) elif attrib == "foregroundColorMarkedSelected": self.markedForegroundSelected = parseColor(value) elif attrib == "backgroundColorMarked": self.markedBackground = parseColor(value) elif attrib == "backgroundColorMarkedSelected": self.markedBackgroundSelected = parseColor(value) elif attrib == "foregroundColorServiceNotAvail": self.serviceNotAvail = parseColor(value) elif attrib == "colorEventProgressbar": self.serviceEventProgressbarColor = parseColor(value) elif attrib == "colorEventProgressbarSelected": self.serviceEventProgressbarColorSelected = parseColor(value) elif attrib == "forgroundColorEventProgressbarBorder": self.serviceEventProgressbarBackColor = parseColor(value) elif attrib == "backgroundColorEventProgressbarBorderSelected": self.serviceEventProgressbarBackColorSelected = parseColor(value) elif attrib == "colorEventProgressbarBorder": self.serviceEventProgressbarBorderColor = parseColor(value) elif attrib == "colorEventProgressbarBorderSelected": self.serviceEventProgressbarBorderColorSelected = parseColor(value) elif attrib == "colorServiceDescription": self.serviceDescriptionColor = parseColor(value) elif attrib == "colorServiceDescriptionSelected": self.serviceDescriptionColorSelected = parseColor(value) elif attrib == "colorRecording": self.recordingColor = parseColor(value) elif attrib == "colorRecordingSelected": self.recordingColorSelected = parseColor(value) elif attrib == "colorAdditionalInfo": self.additionalInfoColor = parseColor(value) elif attrib == "colorAdditionalInfoSelected": self.additionalInfoColorSelected = parseColor(value) elif attrib == "picServiceEventProgressbar": pic = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, value)) if pic: self.picServiceEventProgressbar = pic elif attrib == "serviceItemHeight": self.itemHeight = int(value) elif attrib == "serviceNameFont": self.l.setFont(2, parseFont(value, ((1,1),(1,1)))) self.serviceNameFont = parseFont(value, ((1,1),(1,1))) elif attrib == "serviceInfoFont": self.l.setFont(3, parseFont(value, ((1,1),(1,1)))) name, size = value.split(';') self.serviceInfoFontHeight = int(size) elif attrib == "serviceNumberFont": self.l.setFont(1, parseFont(value, ((1,1),(1,1)))) elif attrib == "additionalInfoFont": self.l.setFont(0, parseFont(value, ((1,1),(1,1)))) self.additionalInfoFont = parseFont(value, ((1,1),(1,1))) elif attrib == "selectionPixmap": pic = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, value)) if pic: self.selectionPixmapStandard = pic if not config.usage.configselection_bigpicons.value: self.instance.setSelectionPicture(self.selectionPixmapStandard) elif attrib == "selectionPixmapHigh": pic = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, value)) if pic: self.selectionPixmapBig = pic if config.usage.configselection_bigpicons.value: self.instance.setSelectionPicture(self.selectionPixmapBig) else: attribs.append((attrib, value)) self.skinAttributes = attribs return GUIComponent.applySkin(self, desktop, parent) def connectSelChanged(self, fnc): if not fnc in self.onSelectionChanged: self.onSelectionChanged.append(fnc) def disconnectSelChanged(self, fnc): if fnc in self.onSelectionChanged: self.onSelectionChanged.remove(fnc) def selectionChanged(self): for x in self.onSelectionChanged: x() def setCurrent(self, ref): self.l.setCurrent(ref) def getCurrent(self): r = eServiceReference() self.l.getCurrent(r) return r def atBegin(self): return self.instance.atBegin() def atEnd(self): return self.instance.atEnd() def moveUp(self): self.instance.moveSelection(self.instance.moveUp) def moveDown(self): self.instance.moveSelection(self.instance.moveDown) def moveToChar(self, char): print "Next char: ", char index = self.l.getNextBeginningWithChar(char) indexup = self.l.getNextBeginningWithChar(char.upper()) if indexup != 0: if (index > indexup or index == 0): index = indexup self.instance.moveSelectionTo(index) print "Moving to character " + str(char) def moveToNextMarker(self): idx = self.l.getNextMarkerPos() self.instance.moveSelectionTo(idx) def moveToPrevMarker(self): idx = self.l.getPrevMarkerPos() self.instance.moveSelectionTo(idx) def moveToIndex(self, index): self.instance.moveSelectionTo(index) def getCurrentIndex(self): return self.instance.getCurrentIndex() GUI_WIDGET = eListbox def postWidgetCreate(self, instance): instance.setWrapAround(True) instance.setContent(self.l) self.selectionChanged_conn = instance.selectionChanged.connect(self.selectionChanged) self.setMode(self.mode) self.textRenderer = eLabel(self.instance) self.textRenderer.resize(eSize(400,0)) self.textRenderer.hide() def preWidgetRemove(self, instance): if self.session: self.session.nav.RecordTimer.on_state_change.remove(self.onTimerEntryStateChange) instance.setContent(None) self.selectionChanged_conn = None config.usage.configselection_showrecordings.removeNotifier(self.getRecordingList) config.usage.configselection_bigpicons.removeNotifier(self.setItemHeight) def getRoot(self): return self.root def getRootServices(self): serviceHandler = eServiceCenter.getInstance() list = serviceHandler.list(self.root) dest = [ ] if list is not None: while 1: s = list.getNext() if s.valid(): dest.append(s.toString()) else: break return dest def setNumberOffset(self, offset): self.numberoffset = offset def setPlayableIgnoreService(self, ref): self.is_playable_ignore = ref def setRoot(self, root, justSet=False): self.root = root self.l.setRoot(root, justSet) if not justSet: self.l.sort() self.selectionChanged() def removeCurrent(self): self.l.removeCurrent() def addService(self, service, beforeCurrent=False): self.l.addService(service, beforeCurrent) def finishFill(self): self.l.FillFinished() self.l.sort() # stuff for multiple marks (edit mode / later multiepg) def clearMarks(self): self.l.initMarked() def isMarked(self, ref): return self.l.isMarked(ref) def addMarked(self, ref): self.l.addMarked(ref) def removeMarked(self, ref): self.l.removeMarked(ref) def getMarked(self): i = self.l i.markedQueryStart() ref = eServiceReference() marked = [ ] while i.markedQueryNext(ref) == 0: marked.append(ref.toString()) ref = eServiceReference() return marked #just for movemode.. only one marked entry.. def setCurrentMarked(self, state): self.l.setCurrentMarked(state) def setMode(self, mode): self.mode = mode self.setItemHeight()
class PowerTimerList(GUIComponent, object): # # | <Service> <Name of the Timer> | # | <start, end> <state> | # def buildTimerEntry(self, timer, processed): screenwidth = getDesktop(0).size().width() timertype = { TIMERTYPE.WAKEUP: _("Wake Up"), TIMERTYPE.WAKEUPTOSTANDBY: _("Wake Up To Standby"), TIMERTYPE.STANDBY: _("Standby"), TIMERTYPE.AUTOSTANDBY: _("Auto Standby"), TIMERTYPE.AUTODEEPSTANDBY: _("Auto Deep Standby"), TIMERTYPE.DEEPSTANDBY: _("Deep Standby"), TIMERTYPE.REBOOT: _("Reboot"), TIMERTYPE.RESTART: _("Restart GUI") }[timer.timerType] afterevent = { AFTEREVENT.NONE: _("Nothing"), AFTEREVENT.WAKEUPTOSTANDBY: _("Wake Up To Standby"), AFTEREVENT.STANDBY: _("Standby"), AFTEREVENT.DEEPSTANDBY: _("Deep Standby") }[timer.afterEvent] height = self.l.getItemSize().height() width = self.l.getItemSize().width() res = [ None ] x = width / 2 res.append((eListboxPythonMultiContent.TYPE_TEXT, self.iconWidth + self.iconMargin, 2, width, self.rowSplit, 0, RT_HALIGN_LEFT|RT_VALIGN_BOTTOM, timertype)) if timer.timerType == TIMERTYPE.AUTOSTANDBY or timer.timerType == TIMERTYPE.AUTODEEPSTANDBY: if self.iconRepeat and timer.autosleeprepeat != "once": res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, self.iconMargin / 2, self.rowSplit + (self.itemHeight - self.rowSplit - self.iconHeight) / 2, self.iconWidth, self.iconHeight, self.iconRepeat)) icon = None if not processed: if timer.state == TimerEntry.StateWaiting: state = _("waiting") icon = self.iconWait elif timer.state == TimerEntry.StatePrepared or timer.state == TimerEntry.StateRunning: state = _("running...") icon = self.iconZapped elif timer.state == TimerEntry.StateEnded: state = _("done!") icon = self.iconDone else: state = _("<unknown>") icon = None else: state = _("done!") icon = self.iconDone res.append((eListboxPythonMultiContent.TYPE_TEXT, 148, 26, width-150, self.itemHeight - self.rowSplit, 2, RT_HALIGN_RIGHT|RT_VALIGN_BOTTOM, _("Delay:") + " " + str(timer.autosleepdelay) + "(" + _("mins") + ")")) else: res.append((eListboxPythonMultiContent.TYPE_TEXT, x+24, 2, x-2-24, self.itemHeight - self.rowSplit, 2, RT_HALIGN_RIGHT|RT_VALIGN_BOTTOM, _('At End:') + ' ' + afterevent)) days = ( _("Mon"), _("Tue"), _("Wed"), _("Thu"), _("Fri"), _("Sat"), _("Sun") ) begin = FuzzyTime(timer.begin) if timer.repeated: repeatedtext = [] flags = timer.repeated for x in (0, 1, 2, 3, 4, 5, 6): if flags & 1 == 1: repeatedtext.append(days[x]) flags >>= 1 if repeatedtext == [_("Mon"), _("Tue"), _("Wed"), _("Thu"), _("Fri"), _("Sat"), _("Sun")]: repeatedtext = _('Everyday') elif repeatedtext == [_("Mon"), _("Tue"), _("Wed"), _("Thu"), _("Fri")]: repeatedtext = _('Weekday') elif repeatedtext == [_("Sat"), _("Sun")]: repeatedtext = _('Weekend') else: repeatedtext = ", ".join(repeatedtext) if self.iconRepeat: res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, 2, self.rowSplit, 20, 20, self.iconRepeat)) else: repeatedtext = begin[0] # date text = repeatedtext + ((" %s ... %s (%d " + _("mins") + ")") % (begin[1], FuzzyTime(timer.end)[1], (timer.end - timer.begin) / 60)) res.append((eListboxPythonMultiContent.TYPE_TEXT, 148, self.itemHeight - self.rowSplit, width-150, self.rowSplit, 2, RT_HALIGN_RIGHT|RT_VALIGN_BOTTOM, text)) icon = None if not processed: if timer.state == TimerEntry.StateWaiting: state = _("waiting") icon = self.iconWait elif timer.state == TimerEntry.StatePrepared: state = _("about to start") icon = self.iconPrepared elif timer.state == TimerEntry.StateRunning: state = _("running...") icon = self.iconZapped elif timer.state == TimerEntry.StateEnded: state = _("done!") icon = self.iconDone else: state = _("<unknown>") icon = None else: state = _("done!") icon = self.iconDone if timer.disabled: state = _("disabled") icon = self.iconDisabled if timer.failed: state = _("failed") icon = self.iconFailed icon and res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, self.iconMargin / 2, (self.rowSplit - self.iconHeight) / 2, self.iconWidth, self.iconHeight, icon)) res.append((eListboxPythonMultiContent.TYPE_TEXT, self.iconMargin + self.iconWidth, self.rowSplit, 126, height - self.rowSplit, 2, RT_HALIGN_LEFT|RT_VALIGN_BOTTOM, state)) line = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, "div-h.png")) res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, 0, height-2, width, 2, line)) return res def __init__(self, list): GUIComponent.__init__(self) self.l = eListboxPythonMultiContent() self.l.setBuildFunc(self.buildTimerEntry) self.serviceNameFont = gFont("Regular", 20) self.font = gFont("Regular", 18) self.eventNameFont = gFont("Regular", 18) self.l.setList(list) self.itemHeight = 50 self.rowSplit = 25 self.iconMargin = 4 self.satPosLeft = 160 self.iconWait = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, "icons/timer_wait.png")) self.iconWidth = self.iconWait.size().width() self.iconHeight = self.iconWait.size().height() self.iconRecording = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, "icons/timer_rec.png")) self.iconPrepared = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, "icons/timer_prep.png")) self.iconDone = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, "icons/timer_done.png")) self.iconRepeat = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, "icons/timer_rep.png")) self.iconZapped = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, "icons/timer_zap.png")) self.iconDisabled = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, "icons/timer_off.png")) self.iconFailed = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, "icons/timer_failed.png")) def applySkin(self, desktop, parent): def itemHeight(value): self.itemHeight = int(value) def setServiceNameFont(value): self.serviceNameFont = parseFont(value, ((1,1),(1,1))) def setEventNameFont(value): self.eventNameFont = parseFont(value, ((1,1),(1,1))) def setFont(value): self.font = parseFont(value, ((1,1),(1,1))) def rowSplit(value): self.rowSplit = int(value) def iconMargin(value): self.iconMargin = int(value) def satPosLeft(value): self.satPosLeft = int(value) for (attrib, value) in list(self.skinAttributes): try: locals().get(attrib)(value) self.skinAttributes.remove((attrib, value)) except: pass self.l.setItemHeight(self.itemHeight) self.l.setFont(0, self.serviceNameFont) self.l.setFont(1, self.font) self.l.setFont(2, self.eventNameFont) return GUIComponent.applySkin(self, desktop, parent) def getCurrent(self): cur = self.l.getCurrentSelection() return cur and cur[0] GUI_WIDGET = eListbox def postWidgetCreate(self, instance): instance.setContent(self.l) self.instance = instance def moveToIndex(self, index): self.instance.moveSelectionTo(index) def getCurrentIndex(self): return self.instance.getCurrentIndex() currentIndex = property(getCurrentIndex, moveToIndex) currentSelection = property(getCurrent) def moveDown(self): self.instance.moveSelection(self.instance.moveDown) def invalidate(self): self.l.invalidate() def entryRemoved(self, idx): self.l.entryRemoved(idx)
class MovieList(GUIComponent): SORT_ALPHANUMERIC = 1 SORT_RECORDED = 2 SHUFFLE = 3 SORT_ALPHANUMERIC_REVERSE = 4 SORT_RECORDED_REVERSE = 5 SORT_ALPHANUMERIC_FLAT = 6 SORT_ALPHANUMERIC_FLAT_REVERSE = 7 SORT_GROUPWISE = 8 LISTTYPE_ORIGINAL = 1 LISTTYPE_COMPACT_DESCRIPTION = 2 LISTTYPE_COMPACT = 3 LISTTYPE_MINIMAL = 4 HIDE_DESCRIPTION = 1 SHOW_DESCRIPTION = 2 def __init__(self, root, list_type=None, sort_type=None, descr_state=None): GUIComponent.__init__(self) self.list = [] self.list_type = list_type or self.LISTTYPE_MINIMAL self.descr_state = descr_state or self.HIDE_DESCRIPTION self.sort_type = sort_type or self.SORT_GROUPWISE self.firstFileEntry = 0 self.parentDirectory = 0 self.fontName = "Regular" self.fontSizesOriginal = (22,18,16) self.fontSizesCompact = (20,14) self.fontSizesMinimal = (20,16) self.itemHeights = (75,37,25) self.pbarShift = 5 self.pbarHeight = 16 self.pbarLargeWidth = 48 self.partIconeShiftMinimal = 5 self.partIconeShiftCompact = 4 self.partIconeShiftOriginal = 5 self.spaceRight = 2 self.spaceIconeText = 2 self.iconsWidth = 22 self.trashShift = 1 self.dirShift = 1 self.columnsOriginal = (180,200) self.columnsCompactDescription = (120,140,154) self.compactColumn = 200 self.treeDescription = 165 self.reloadDelayTimer = None self.l = eListboxPythonMultiContent() self.tags = set() self.root = None self._playInBackground = None self._char = '' if root is not None: self.reload(root) self.l.setBuildFunc(self.buildMovieListEntry) self.onSelectionChanged = [ ] self.iconPart = [] for part in range(5): self.iconPart.append(LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/part_%d_4.png" % part))) self.iconMovieRec = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/part_new.png")) self.iconMoviePlay = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/movie_play.png")) self.iconMoviePlayRec = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/movie_play_rec.png")) self.iconUnwatched = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/part_unwatched.png")) self.iconFolder = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/folder.png")) self.iconTrash = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/trashcan.png")) self.runningTimers = {} self.updateRecordings() def get_playInBackground(self): return self._playInBackground def set_playInBackground(self, value): if self._playInBackground is not value: index = self.findService(self._playInBackground) if index is not None: self.invalidateItem(index) self.l.invalidateEntry(index) index = self.findService(value) if index is not None: self.invalidateItem(index) self.l.invalidateEntry(index) self._playInBackground = value playInBackground = property(get_playInBackground, set_playInBackground) def updateRecordings(self, timer=None): if timer is not None: if timer.justplay: return result = {} for timer in NavigationInstance.instance.RecordTimer.timer_list: if timer.isRunning() and not timer.justplay: result[os.path.split(timer.Filename)[1]+'.ts'] = timer if self.runningTimers == result: return self.runningTimers = result if timer is not None: if self.reloadDelayTimer is not None: self.reloadDelayTimer.stop() self.reloadDelayTimer = eTimer() self.reloadDelayTimer.callback.append(self.reload) self.reloadDelayTimer.start(5000, 1) def connectSelChanged(self, fnc): if not fnc in self.onSelectionChanged: self.onSelectionChanged.append(fnc) def disconnectSelChanged(self, fnc): if fnc in self.onSelectionChanged: self.onSelectionChanged.remove(fnc) def selectionChanged(self): for x in self.onSelectionChanged: x() def setListType(self, type): if type != self.list_type: self.list_type = type self.redrawList() def setDescriptionState(self, val): self.descr_state = val def setSortType(self, type): self.sort_type = type def applySkin(self, desktop, parent): def warningWrongSkinParameter(string): print "[MovieList] wrong '%s' skin parameters" % string def fontName(value): self.fontName = value def fontSizesOriginal(value): self.fontSizesOriginal = map(int, value.split(",")) if len(self.fontSizesOriginal) != 3: warningWrongSkinParameter(attrib) def fontSizesCompact(value): self.fontSizesCompact = map(int, value.split(",")) if len(self.fontSizesCompact) != 2: warningWrongSkinParameter(attrib) def fontSizesMinimal(value): self.fontSizesMinimal = map(int, value.split(",")) if len(self.fontSizesMinimal) != 2: warningWrongSkinParameter(attrib) def itemHeights(value): self.itemHeights = map(int, value.split(",")) if len(self.itemHeights) != 3: warningWrongSkinParameter(attrib) def pbarShift(value): self.pbarShift = int(value) def pbarHeight(value): self.pbarHeight = int(value) def pbarLargeWidth(value): self.pbarLargeWidth = int(value) def partIconeShiftMinimal(value): self.partIconeShiftMinimal = int(value) def partIconeShiftCompact(value): self.partIconeShiftCompact = int(value) def partIconeShiftOriginal(value): self.partIconeShiftOriginal = int(value) def spaceIconeText(value): self.spaceIconeText = int(value) def iconsWidth(value): self.iconsWidth = int(value) def trashShift(value): self.trashShift = int(value) def dirShift(value): self.dirShift = int(value) def spaceRight(value): self.spaceRight = int(value) def columnsOriginal(value): self.columnsOriginal = map(int, value.split(",")) if len(self.columnsOriginal) != 2: warningWrongSkinParameter(attrib) def columnsCompactDescription(value): self.columnsCompactDescription = map(int, value.split(",")) if len(self.columnsCompactDescription) != 3: warningWrongSkinParameter(attrib) def compactColumn(value): self.compactColumn = int(value) def treeDescription(value): self.treeDescription = int(value) for (attrib, value) in self.skinAttributes[:]: try: locals().get(attrib)(value) self.skinAttributes.remove((attrib, value)) except: pass self.redrawList() return GUIComponent.applySkin(self, desktop, parent) def redrawList(self): if self.list_type == MovieList.LISTTYPE_ORIGINAL: for i in range(3): self.l.setFont(i, gFont(self.fontName, self.fontSizesOriginal[i])) self.itemHeight = self.itemHeights[0] elif self.list_type == MovieList.LISTTYPE_COMPACT_DESCRIPTION or self.list_type == MovieList.LISTTYPE_COMPACT: for i in range(2): self.l.setFont(i, gFont(self.fontName, self.fontSizesCompact[i])) self.itemHeight = self.itemHeights[1] else: for i in range(2): self.l.setFont(i, gFont(self.fontName, self.fontSizesMinimal[i])) self.itemHeight = self.itemHeights[2] self.l.setItemHeight(self.itemHeight) def invalidateItem(self, index): x = self.list[index] self.list[index] = (x[0], x[1], x[2], None) def invalidateCurrentItem(self): self.invalidateItem(self.getCurrentIndex()) def buildMovieListEntry(self, serviceref, info, begin, data): width = self.l.getItemSize().width() iconSize = self.iconsWidth space = self.spaceIconeText r = self.spaceRight pathName = serviceref.getPath() res = [ None ] if serviceref.flags & eServiceReference.mustDescent: # Directory # Name is full path name valign_center = 0 if self.list_type == MovieList.LISTTYPE_MINIMAL: valign_center = RT_VALIGN_CENTER x = iconSize + space tn = self.treeDescription if info is None: # Special case: "parent" txt = ".." else: p = os.path.split(pathName) if not p[1]: # if path ends in '/', p is blank. p = os.path.split(p[0]) txt = p[1] if txt == ".Trash": res.append(MultiContentEntryPixmapAlphaTest(pos=(0,self.trashShift), size=(iconSize,self.iconTrash.size().height()), png=self.iconTrash)) res.append(MultiContentEntryText(pos=(x, 0), size=(width-x-tn-r, self.itemHeight), font = 0, flags = RT_HALIGN_LEFT|valign_center, text = _("Deleted items"))) res.append(MultiContentEntryText(pos=(width-tn-r, 0), size=(tn, self.itemHeight), font=1, flags=RT_HALIGN_RIGHT|valign_center, text=_("Trash can"))) return res res.append(MultiContentEntryPixmapAlphaTest(pos=(0,self.dirShift), size=(iconSize,iconSize), png=self.iconFolder)) res.append(MultiContentEntryText(pos=(x, 0), size=(width-x-tn-r, self.itemHeight), font = 0, flags = RT_HALIGN_LEFT|valign_center, text = txt)) res.append(MultiContentEntryText(pos=(width-tn-r, 0), size=(tn, self.itemHeight), font=1, flags=RT_HALIGN_RIGHT|valign_center, text=_("Directory"))) return res if (data == -1) or (data is None): data = MovieListData() cur_idx = self.l.getCurrentSelectionIndex() x = self.list[cur_idx] # x = ref,info,begin,... if config.usage.load_length_of_movies_in_moviellist.value: data.len = x[1].getLength(x[0]) #recalc the movie length... else: data.len = 0 #dont recalc movielist to speedup loading the list self.list[cur_idx] = (x[0], x[1], x[2], data) #update entry in list... so next time we don't need to recalc data.txt = info.getName(serviceref) if config.movielist.hide_extensions.value: fileName, fileExtension = os.path.splitext(data.txt) if fileExtension in KNOWN_EXTENSIONS: data.txt = fileName data.icon = None data.part = None if os.path.split(pathName)[1] in self.runningTimers: if self.playInBackground and serviceref == self.playInBackground: data.icon = self.iconMoviePlayRec else: data.icon = self.iconMovieRec elif self.playInBackground and serviceref == self.playInBackground: data.icon = self.iconMoviePlay else: switch = config.usage.show_icons_in_movielist.value data.part = moviePlayState(pathName + '.cuts', serviceref, data.len) if switch == 'i': if data.part is None: if config.usage.movielist_unseen.value: data.icon = self.iconUnwatched else: data.icon = self.iconPart[data.part // 25] elif switch == 'p' or switch == 's': if data.part is None: if config.usage.movielist_unseen.value: data.part = 0 data.partcol = 0x808080 else: data.partcol = 0xf0f0f0 service = ServiceReference(info.getInfoString(serviceref, iServiceInformation.sServiceref)) if service is None: data.serviceName = None else: data.serviceName = service.getServiceName() data.description = info.getInfoString(serviceref, iServiceInformation.sDescription) len = data.len if len > 0: len = "%d:%02d" % (len / 60, len % 60) else: len = "" if data.icon is not None: if self.list_type in (MovieList.LISTTYPE_COMPACT_DESCRIPTION,MovieList.LISTTYPE_COMPACT): pos = (0,self.partIconeShiftCompact) elif self.list_type == MovieList.LISTTYPE_ORIGINAL: pos = (0,self.partIconeShiftOriginal) else: pos = (0,self.partIconeShiftMinimal) res.append(MultiContentEntryPixmapAlphaTest(pos=pos, size=(iconSize,data.icon.size().height()), png=data.icon)) switch = config.usage.show_icons_in_movielist.value if switch in ('p', 's'): if switch == 'p': iconSize = self.pbarLargeWidth if data.part is not None: res.append(MultiContentEntryProgress(pos=(0,self.pbarShift), size=(iconSize, self.pbarHeight), percent=data.part, borderWidth=2, foreColor=data.partcol, foreColorSelected=None, backColor=None, backColorSelected=None)) elif switch == 'i': pass else: iconSize = 0 begin_string = "" if begin > 0: begin_string = ', '.join(FuzzyTime(begin, inPast = True)) ih = self.itemHeight if self.list_type == MovieList.LISTTYPE_ORIGINAL: fc, sc = self.columnsOriginal[0], self.columnsOriginal[1] ih1 = (ih * 2) / 5 # 75 -> 30 ih2 = (ih * 2) / 3 # 75 -> 50 res.append(MultiContentEntryText(pos=(iconSize+space, 0), size=(width-fc-r, ih1), font = 0, flags = RT_HALIGN_LEFT, text=data.txt)) if self.tags: res.append(MultiContentEntryText(pos=(width-fc-r, 0), size=(fc, ih1), font = 2, flags = RT_HALIGN_RIGHT, text = info.getInfoString(serviceref, iServiceInformation.sTags))) if data.serviceName: res.append(MultiContentEntryText(pos=(sc-r, ih2), size=(sc, ih2-ih1), font = 1, flags = RT_HALIGN_LEFT, text = data.serviceName)) else: if data.serviceName: res.append(MultiContentEntryText(pos=(width-fc-r, 0), size=(fc, ih1), font = 2, flags = RT_HALIGN_RIGHT, text = data.serviceName)) res.append(MultiContentEntryText(pos=(0, ih1), size=(width-r, ih2-ih1), font=1, flags=RT_HALIGN_LEFT, text=data.description)) res.append(MultiContentEntryText(pos=(0, ih2), size=(sc-r, ih-ih2), font=1, flags=RT_HALIGN_LEFT, text=begin_string)) if len: res.append(MultiContentEntryText(pos=(width-sc-r, ih2), size=(sc, ih-ih2), font=1, flags=RT_HALIGN_RIGHT, text=len)) elif self.list_type == MovieList.LISTTYPE_COMPACT_DESCRIPTION: ih1 = ((ih * 8) + 14) / 15 # 37 -> 20, round up if len: lenSize = 58 * ih / 37 else: lenSize = 0 fc, sc, tc = self.columnsCompactDescription[0], self.columnsCompactDescription[1], self.columnsCompactDescription[2] res.append(MultiContentEntryText(pos=(iconSize+space, 0), size=(width-sc-r, ih1), font = 0, flags = RT_HALIGN_LEFT, text = data.txt)) res.append(MultiContentEntryText(pos=(0, ih1), size=(width-tc-lenSize-r, ih-ih1), font=1, flags=RT_HALIGN_LEFT, text=data.description)) res.append(MultiContentEntryText(pos=(width-fc-r, 6), size=(fc, ih1), font=1, flags=RT_HALIGN_RIGHT, text=begin_string)) if data.serviceName: res.append(MultiContentEntryText(pos=(width-tc-lenSize-r, ih1), size=(tc, ih-ih1), font = 1, flags = RT_HALIGN_RIGHT, text = data.serviceName)) if lenSize: res.append(MultiContentEntryText(pos=(width-lenSize-r, ih1), size=(lenSize, ih-ih1), font=1, flags=RT_HALIGN_RIGHT, text=len)) elif self.list_type == MovieList.LISTTYPE_COMPACT: col = self.compactColumn ih1 = ((ih * 8) + 14) / 15 # 37 -> 20, round up if len: lenSize = 2 * ih else: lenSize = 0 res.append(MultiContentEntryText(pos=(iconSize+space, 0), size=(width-lenSize-iconSize-space-r, ih1), font = 0, flags = RT_HALIGN_LEFT, text = data.txt)) if self.tags: res.append(MultiContentEntryText(pos=(width-col-r, ih1), size=(col, ih-ih1), font = 1, flags = RT_HALIGN_RIGHT, text = info.getInfoString(serviceref, iServiceInformation.sTags))) if data.serviceName: res.append(MultiContentEntryText(pos=(col, ih1), size=(col, ih-ih1), font = 1, flags = RT_HALIGN_LEFT, text = data.serviceName)) else: if data.serviceName: res.append(MultiContentEntryText(pos=(width-col-r, ih1), size=(col, ih-ih1), font = 1, flags = RT_HALIGN_RIGHT, text = data.serviceName)) res.append(MultiContentEntryText(pos=(0, ih1), size=(col, ih-ih1), font=1, flags=RT_HALIGN_LEFT, text=begin_string)) if lenSize: res.append(MultiContentEntryText(pos=(width-lenSize-r, 0), size=(lenSize, ih1), font=0, flags=RT_HALIGN_RIGHT, text=len)) else: if (self.descr_state == MovieList.SHOW_DESCRIPTION) or not len: dateSize = ih * 145 / 25 # 25 -> 145 res.append(MultiContentEntryText(pos=(iconSize+space, 0), size=(width-iconSize-space-dateSize-r, ih), font = 0, flags = RT_HALIGN_LEFT|RT_VALIGN_CENTER, text = data.txt)) res.append(MultiContentEntryText(pos=(width-dateSize-r, 4), size=(dateSize, ih), font=1, flags=RT_HALIGN_RIGHT|RT_VALIGN_CENTER, text=begin_string)) else: lenSize = ih * 3 # 25 -> 75 res.append(MultiContentEntryText(pos=(iconSize+space, 0), size=(width-lenSize-iconSize-space-r, ih), font = 0, flags = RT_HALIGN_LEFT, text = data.txt)) res.append(MultiContentEntryText(pos=(width-lenSize-r, 0), size=(lenSize, ih), font=0, flags=RT_HALIGN_RIGHT, text=len)) return res def moveToFirstMovie(self): if self.firstFileEntry < len(self.list): self.instance.moveSelectionTo(self.firstFileEntry) else: # there are no movies, just directories... self.moveToFirst() def moveToParentDirectory(self): if self.parentDirectory < len(self.list): self.instance.moveSelectionTo(self.parentDirectory) else: self.moveToFirst() def moveToLast(self): if self.list: self.instance.moveSelectionTo(len(self.list) - 1) def moveToFirst(self): if self.list: self.instance.moveSelectionTo(0) def moveToIndex(self, index): self.instance.moveSelectionTo(index) def getCurrentIndex(self): return self.instance.getCurrentIndex() def getCurrentEvent(self): l = self.l.getCurrentSelection() return l and l[0] and l[1] and l[1].getEvent(l[0]) def getCurrent(self): l = self.l.getCurrentSelection() return l and l[0] def getItem(self, index): if self.list: if len(self.list) > index: return self.list[index] and self.list[index][0] GUI_WIDGET = eListbox def postWidgetCreate(self, instance): instance.setContent(self.l) instance.selectionChanged.get().append(self.selectionChanged) def preWidgetRemove(self, instance): instance.setContent(None) instance.selectionChanged.get().remove(self.selectionChanged) def reload(self, root = None, filter_tags = None): if self.reloadDelayTimer is not None: self.reloadDelayTimer.stop() self.reloadDelayTimer = None if root is not None: self.load(root, filter_tags) else: self.load(self.root, filter_tags) self.l.setList(self.list) def removeService(self, service): index = self.findService(service) if index is not None: del self.list[index] self.l.setList(self.list) def findService(self, service): if service is None: return None for index, l in enumerate(self.list): if l[0] == service: return index return None def __len__(self): return len(self.list) def __getitem__(self, index): return self.list[index] def __iter__(self): return self.list.__iter__() def load(self, root, filter_tags): # this lists our root service, then building a # nice list del self.list[:] serviceHandler = eServiceCenter.getInstance() numberOfDirs = 0 reflist = root and serviceHandler.list(root) if reflist is None: print "listing of movies failed" return realtags = set() autotags = {} rootPath = os.path.normpath(root.getPath()); parent = None # Don't navigate above the "root" if len(rootPath) > 1 and (os.path.realpath(rootPath) != config.movielist.root.value): parent = os.path.split(os.path.normpath(rootPath))[0] if parent and (parent not in defaultInhibitDirs): # enigma wants an extra '/' appended if not parent.endswith('/'): parent += '/' ref = eServiceReference("2:0:1:0:0:0:0:0:0:0:" + parent) ref.flags = eServiceReference.flagDirectory self.list.append((ref, None, 0, -1)) numberOfDirs += 1 while 1: serviceref = reflist.getNext() if not serviceref.valid(): break if config.ParentalControl.servicepinactive.value and config.ParentalControl.storeservicepin.value != "never": from Components.ParentalControl import parentalControl if not parentalControl.sessionPinCached and parentalControl.isProtected(serviceref): continue info = serviceHandler.info(serviceref) if info is None: info = justStubInfo begin = info.getInfo(serviceref, iServiceInformation.sTimeCreate) if serviceref.flags & eServiceReference.mustDescent: self.list.append((serviceref, info, begin, -1)) numberOfDirs += 1 continue # convert separe-separated list of tags into a set this_tags = info.getInfoString(serviceref, iServiceInformation.sTags).split(' ') name = info.getName(serviceref) if this_tags == ['']: # No tags? Auto tag! this_tags = name.replace(',',' ').replace('.',' ').split() # For auto tags, we are keeping a (tag, movies) dictionary. #It will be used later to check if movies have a complete sentence in common. for tag in this_tags: if autotags.has_key(tag): autotags[tag].append(name) else: autotags[tag] = [name] else: realtags.update(this_tags) # filter_tags is either None (which means no filter at all), or # a set. In this case, all elements of filter_tags must be present, # otherwise the entry will be dropped. if filter_tags is not None: this_tags = set(this_tags) if not this_tags.issuperset(filter_tags): print "Skipping", name, "tags=", this_tags, " filter=", filter_tags continue self.list.append((serviceref, info, begin, -1)) self.firstFileEntry = numberOfDirs self.parentDirectory = 0 if self.sort_type == MovieList.SORT_ALPHANUMERIC: self.list.sort(key=self.buildAlphaNumericSortKey) elif self.sort_type == MovieList.SORT_ALPHANUMERIC_FLAT: self.list.sort(key=self.buildAlphaNumericFlatSortKey) elif self.sort_type == MovieList.SORT_ALPHANUMERIC_FLAT_REVERSE: self.list.sort(key=self.buildAlphaNumericFlatSortKey, reverse = True) elif self.sort_type == MovieList.SORT_RECORDED: self.list.sort(key=self.buildBeginTimeSortKey) else: #always sort first this way to avoid shuffle and reverse-sort directories self.list.sort(key=self.buildGroupwiseSortkey) if self.sort_type == MovieList.SHUFFLE: dirlist = self.list[:numberOfDirs] shufflelist = self.list[numberOfDirs:] random.shuffle(shufflelist) self.list = dirlist + shufflelist elif self.sort_type == MovieList.SORT_ALPHANUMERIC_REVERSE: self.list = self.list[:numberOfDirs] + sorted(self.list[numberOfDirs:], key=self.buildAlphaNumericSortKey, reverse = True) elif self.sort_type == MovieList.SORT_RECORDED_REVERSE: self.list = self.list[:numberOfDirs] + sorted(self.list[numberOfDirs:], key=self.buildBeginTimeSortKey, reverse = True) if self.root and numberOfDirs > 0: rootPath = os.path.normpath(self.root.getPath()) if not rootPath.endswith('/'): rootPath += '/' if rootPath != parent: # with new sort types directories may be in between files, so scan whole # list for parentDirectory index. Usually it is the first one anyway for index, item in enumerate(self.list): if item[0].flags & eServiceReference.mustDescent: itempath = os.path.normpath(item[0].getPath()) if not itempath.endswith('/'): itempath += '/' if itempath == rootPath: self.parentDirectory = index break self.root = root # finally, store a list of all tags which were found. these can be presented # to the user to filter the list # ML: Only use the tags that occur more than once in the list OR that were # really in the tag set of some file. # reverse the dictionary to see which unique movie each tag now references rautotags = {} for tag, movies in autotags.items(): if (len(movies) > 1): movies = tuple(movies) # a tuple can be hashed, but a list not item = rautotags.get(movies, []) if not item: rautotags[movies] = item item.append(tag) self.tags = {} for movies, tags in rautotags.items(): movie = movies[0] # format the tag lists so that they are in 'original' order tags.sort(key = movie.find) first = movie.find(tags[0]) last = movie.find(tags[-1]) + len(tags[-1]) match = movie start = 0 end = len(movie) # Check if the set has a complete sentence in common, and how far for m in movies[1:]: if m[start:end] != match: if not m.startswith(movie[:last]): start = first if not m.endswith(movie[first:]): end = last match = movie[start:end] if m[start:end] != match: match = '' break # Adding the longest common sentence to the tag list if match: self.tags[match] = set(tags) else: match = ' '.join(tags) if (len(match) > 2) or (match in realtags): #Omit small words, only for auto tags self.tags[match] = set(tags) # Adding the realtags to the tag list for tag in realtags: self.tags[tag] = set([tag]) def buildAlphaNumericSortKey(self, x): # x = ref,info,begin,... ref = x[0] name = x[1] and x[1].getName(ref) if ref.flags & eServiceReference.mustDescent: return (0, name and name.lower() or "", -x[2]) return (1, name and name.lower() or "", -x[2]) def buildAlphaNumericFlatSortKey(self, x): # x = ref,info,begin,... ref = x[0] name = x[1] and x[1].getName(ref) if name and ref.flags & eServiceReference.mustDescent: # only use directory basename for sorting p = os.path.split(name) if not p[1]: # if path ends in '/', p is blank. p = os.path.split(p[0]) name = p[1] # print "Sorting for -%s-" % name return (1, name and name.lower() or "", -x[2]) def buildBeginTimeSortKey(self, x): ref = x[0] if ref.flags & eServiceReference.mustDescent: return (0, x[1] and x[1].getName(ref).lower() or "") return (1, -x[2]) def buildGroupwiseSortkey(self, x): # Sort recordings by date, sort MP3 and stuff by name ref = x[0] if ref.type >= eServiceReference.idUser: return self.buildAlphaNumericSortKey(x) else: return self.buildBeginTimeSortKey(x) def moveTo(self, serviceref): index = self.findService(serviceref) if index is not None: self.instance.moveSelectionTo(index) return True return False def moveDown(self): self.instance.moveSelection(self.instance.moveDown) def moveUp(self): self.instance.moveSelection(self.instance.moveUp) def moveToChar(self, char, lbl=None): self._char = char self._lbl = lbl if lbl: lbl.setText(self._char) lbl.visible = True self.moveToCharTimer = eTimer() self.moveToCharTimer.callback.append(self._moveToChrStr) self.moveToCharTimer.start(1000, True) #time to wait for next key press to decide which letter to use... def moveToString(self, char, lbl=None): self._char = self._char + char.upper() self._lbl = lbl if lbl: lbl.setText(self._char) lbl.visible = True self.moveToCharTimer = eTimer() self.moveToCharTimer.callback.append(self._moveToChrStr) self.moveToCharTimer.start(1000, True) #time to wait for next key press to decide which letter to use... def _moveToChrStr(self): currentIndex = self.instance.getCurrentIndex() found = False if currentIndex < (len(self.list) - 1): itemsBelow = self.list[currentIndex + 1:] #first search the items below the selection for index, item in enumerate(itemsBelow): ref = item[0] itemName = getShortName(item[1].getName(ref).upper(), ref) if len(self._char) == 1 and itemName.startswith(self._char): found = True self.instance.moveSelectionTo(index + currentIndex + 1) break elif len(self._char) > 1 and itemName.find(self._char) >= 0: found = True self.instance.moveSelectionTo(index + currentIndex + 1) break if found == False and currentIndex > 0: itemsAbove = self.list[1:currentIndex] #first item (0) points parent folder - no point to include for index, item in enumerate(itemsAbove): ref = item[0] itemName = getShortName(item[1].getName(ref).upper(), ref) if len(self._char) == 1 and itemName.startswith(self._char): found = True self.instance.moveSelectionTo(index + 1) break elif len(self._char) > 1 and itemName.find(self._char) >= 0: found = True self.instance.moveSelectionTo(index + 1) break self._char = '' if self._lbl: self._lbl.visible = False
class MovieList(GUIComponent): SORT_ALPHANUMERIC = 1 SORT_RECORDED = 2 SHUFFLE = 3 SORT_ALPHANUMERIC_REVERSE = 4 SORT_RECORDED_REVERSE = 5 SORT_ALPHANUMERIC_FLAT = 6 SORT_ALPHANUMERIC_FLAT_REVERSE = 7 SORT_GROUPWISE = 8 SORT_ALPHA_DATE_OLDEST_FIRST = 9 SORT_ALPHAREV_DATE_NEWEST_FIRST = 10 HIDE_DESCRIPTION = 1 SHOW_DESCRIPTION = 2 def __init__(self, root, sort_type=None, descr_state=None): GUIComponent.__init__(self) self.list = [] self.descr_state = descr_state or self.HIDE_DESCRIPTION self.sort_type = sort_type or self.SORT_GROUPWISE self.firstFileEntry = 0 self.parentDirectory = 0 self.fontName = "Regular" self.fontSize = 20 self.listHeight = None self.listWidth = None self.pbarShift = 5 self.pbarHeight = 16 self.pbarLargeWidth = 48 self.pbarColour = 0x206333 self.pbarColourSeen = 0xffc71d self.pbarColourRec = 0xff001d self.partIconeShift = 5 self.spaceRight = 2 self.spaceIconeText = 2 self.iconsWidth = 22 self.trashShift = 1 self.dirShift = 1 self.dateWidth = 150 self.reloadDelayTimer = None self.l = eListboxPythonMultiContent() self.tags = set() self.root = None self._playInBackground = None self._playInForeground = None self._char = '' if root is not None: self.reload(root) self.l.setBuildFunc(self.buildMovieListEntry) self.onSelectionChanged = [] self.iconPart = [] for part in range(5): self.iconPart.append( LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, "icons/part_%d_4.png" % part))) self.iconMovieRec = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, "icons/part_new.png")) self.iconMoviePlay = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, "icons/movie_play.png")) self.iconMoviePlayRec = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, "icons/movie_play_rec.png")) self.iconUnwatched = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, "icons/part_unwatched.png")) self.iconFolder = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, "icons/folder.png")) self.iconTrash = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, "icons/trashcan.png")) self.runningTimers = {} self.updateRecordings() self.updatePlayPosCache() def get_playInBackground(self): return self._playInBackground def set_playInBackground(self, value): if self._playInBackground is not value: index = self.findService(self._playInBackground) if index is not None: self.invalidateItem(index) self.l.invalidateEntry(index) index = self.findService(value) if index is not None: self.invalidateItem(index) self.l.invalidateEntry(index) self._playInBackground = value playInBackground = property(get_playInBackground, set_playInBackground) def get_playInForeground(self): return self._playInForeground def set_playInForeground(self, value): self._playInForeground = value playInForeground = property(get_playInForeground, set_playInForeground) def updatePlayPosCache(self): from Screens.InfoBarGenerics import updateresumePointCache updateresumePointCache() def updateRecordings(self, timer=None): if timer is not None: if timer.justplay: return result = {} for timer in NavigationInstance.instance.RecordTimer.timer_list: if timer.isRunning() and not timer.justplay: result[os.path.split(timer.Filename)[1] + '.ts'] = timer if self.runningTimers == result: return self.runningTimers = result if timer is not None: if self.reloadDelayTimer is not None: self.reloadDelayTimer.stop() self.reloadDelayTimer = eTimer() self.reloadDelayTimer.callback.append(self.reload) self.reloadDelayTimer.start(5000, 1) def connectSelChanged(self, fnc): if not fnc in self.onSelectionChanged: self.onSelectionChanged.append(fnc) def disconnectSelChanged(self, fnc): if fnc in self.onSelectionChanged: self.onSelectionChanged.remove(fnc) def selectionChanged(self): for x in self.onSelectionChanged: x() def setDescriptionState(self, val): self.descr_state = val def setSortType(self, type): self.sort_type = type def applySkin(self, desktop, parent): def warningWrongSkinParameter(string): print "[MovieList] wrong '%s' skin parameters" % string def font(value): font = skin.parseFont(value, ((1, 1), (1, 1))) self.fontName = font.family self.fontSize = font.pointSize def pbarShift(value): self.pbarShift = int(value) def pbarHeight(value): self.pbarHeight = int(value) def pbarLargeWidth(value): self.pbarLargeWidth = int(value) def pbarColour(value): self.pbarColour = skin.parseColor(value).argb() def pbarColourSeen(value): self.pbarColourSeen = skin.parseColor(value).argb() def pbarColourRec(value): self.pbarColourRec = skin.parseColor(value).argb() def partIconeShift(value): self.partIconeShift = int(value) def spaceIconeText(value): self.spaceIconeText = int(value) def iconsWidth(value): self.iconsWidth = int(value) def trashShift(value): self.trashShift = int(value) def dirShift(value): self.dirShift = int(value) def spaceRight(value): self.spaceRight = int(value) def dateWidth(value): self.dateWidth = int(value) for (attrib, value) in self.skinAttributes[:]: try: locals().get(attrib)(value) self.skinAttributes.remove((attrib, value)) except: pass rc = GUIComponent.applySkin(self, desktop, parent) self.listHeight = self.instance.size().height() self.listWidth = self.instance.size().width() self.setFontsize() self.setItemsPerPage() return rc def setItemsPerPage(self): if self.listHeight > 0: itemHeight = self.listHeight / config.movielist.itemsperpage.value else: itemHeight = 25 # some default (270/5) self.itemHeight = itemHeight self.l.setItemHeight(itemHeight) self.instance.resize( eSize(self.listWidth, self.listHeight / itemHeight * itemHeight)) def setFontsize(self): self.l.setFont( 0, gFont(self.fontName, self.fontSize + config.movielist.fontsize.value)) self.l.setFont( 1, gFont(self.fontName, (self.fontSize - 3) + config.movielist.fontsize.value)) def invalidateItem(self, index): x = self.list[index] self.list[index] = (x[0], x[1], x[2], None) def invalidateCurrentItem(self): self.invalidateItem(self.getCurrentIndex()) def buildMovieListEntry(self, serviceref, info, begin, data): switch = config.usage.show_icons_in_movielist.value width = self.l.getItemSize().width() dateWidth = self.dateWidth iconSize = self.iconsWidth space = self.spaceIconeText r = self.spaceRight pathName = serviceref.getPath() res = [None] if serviceref.flags & eServiceReference.mustDescent: # Directory # Name is full path name if info is None: # Special case: "parent" txt = ".." else: p = os.path.split(pathName) if not p[1]: # if path ends in '/', p is blank. p = os.path.split(p[0]) txt = p[1] if txt == ".Trash": res.append( MultiContentEntryPixmapAlphaBlend( pos=(0, self.trashShift), size=(iconSize, self.iconTrash.size().height()), png=self.iconTrash)) res.append( MultiContentEntryText(pos=(iconSize + space, 0), size=(width - 166, self.itemHeight), font=0, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER, text=_("Deleted items"))) res.append( MultiContentEntryText(pos=(width - 145 - r, 0), size=(145, self.itemHeight), font=1, flags=RT_HALIGN_RIGHT | RT_VALIGN_CENTER, text=_("Trash can"))) return res res.append( MultiContentEntryPixmapAlphaBlend(pos=(0, self.dirShift), size=(iconSize, iconSize), png=self.iconFolder)) res.append( MultiContentEntryText(pos=(iconSize + space, 0), size=(width - 166, self.itemHeight), font=0, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER, text=txt)) res.append( MultiContentEntryText(pos=(width - 145 - r, 0), size=(145, self.itemHeight), font=1, flags=RT_HALIGN_RIGHT | RT_VALIGN_CENTER, text=_("Directory"))) return res if data == -1 or data is None: data = MovieListData() cur_idx = self.l.getCurrentSelectionIndex() x = self.list[cur_idx] # x = ref,info,begin,... data.len = 0 #dont recalc movielist to speedup loading the list self.list[cur_idx] = ( x[0], x[1], x[2], data ) #update entry in list... so next time we don't need to recalc data.txt = info.getName(serviceref) if config.movielist.hide_extensions.value: fileName, fileExtension = os.path.splitext(data.txt) if fileExtension in KNOWN_EXTENSIONS: data.txt = fileName data.icon = None data.part = None if os.path.split(pathName)[1] in self.runningTimers: if switch == 'i': if (self.playInBackground or self.playInForeground ) and serviceref == (self.playInBackground or self.playInForeground): data.icon = self.iconMoviePlayRec else: data.icon = self.iconMovieRec elif switch in ('p', 's'): data.part = 100 if (self.playInBackground or self.playInForeground ) and serviceref == (self.playInBackground or self.playInForeground): data.partcol = self.pbarColourSeen else: data.partcol = self.pbarColourRec elif (self.playInBackground or self.playInForeground) and serviceref == ( self.playInBackground or self.playInForeground): data.icon = self.iconMoviePlay else: data.part = moviePlayState(pathName + '.cuts', serviceref, data.len) if switch == 'i': if data.part is not None and data.part > 0: data.icon = self.iconPart[data.part // 25] else: if config.usage.movielist_unseen.value: data.icon = self.iconUnwatched elif switch in ('p', 's'): if data.part is not None and data.part > 0: data.partcol = self.pbarColourSeen else: if config.usage.movielist_unseen.value: data.part = 100 data.partcol = self.pbarColour len = data.len if len > 0: len = "%d:%02d" % (len / 60, len % 60) else: len = "" if data: pos = (0, self.partIconeShift) if switch == 'i' and hasattr(data, 'icon') and data.icon is not None: res.append( MultiContentEntryPixmapAlphaBlend( pos=pos, size=(iconSize, data.icon.size().height()), png=data.icon)) elif switch in ('p', 's'): if switch == 'p': iconSize = self.pbarLargeWidth if hasattr(data, 'part') and data.part > 0: res.append( MultiContentEntryProgress(pos=(0, self.pbarShift), size=(iconSize, self.pbarHeight), percent=data.part, borderWidth=2, foreColor=data.partcol, foreColorSelected=None, backColor=None, backColorSelected=None)) elif hasattr(data, 'icon') and data.icon is not None: res.append( MultiContentEntryPixmapAlphaBlend( pos=(0, self.pbarShift), size=(iconSize, self.pbarHeight), png=data.icon)) begin_string = "" if begin > 0: begin_string = ', '.join(FuzzyTime(begin, inPast=True)) ih = self.itemHeight res.append( MultiContentEntryText(pos=(iconSize + space, 0), size=(width - iconSize - space - dateWidth - r, ih), font=0, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER, text=data.txt)) res.append( MultiContentEntryText(pos=(width - dateWidth - r, 0), size=(dateWidth, ih), font=1, flags=RT_HALIGN_RIGHT | RT_VALIGN_CENTER, text=begin_string)) return res def moveToFirstMovie(self): if self.firstFileEntry < len(self.list): self.instance.moveSelectionTo(self.firstFileEntry) else: # there are no movies, just directories... self.moveToFirst() def moveToParentDirectory(self): if self.parentDirectory < len(self.list): self.instance.moveSelectionTo(self.parentDirectory) else: self.moveToFirst() def moveToLast(self): if self.list: self.instance.moveSelectionTo(len(self.list) - 1) def moveToFirst(self): if self.list: self.instance.moveSelectionTo(0) def moveToIndex(self, index): self.instance.moveSelectionTo(index) def getCurrentIndex(self): return self.instance.getCurrentIndex() def getCurrentEvent(self): l = self.l.getCurrentSelection() return l and l[0] and l[1] and l[1].getEvent(l[0]) def getCurrent(self): l = self.l.getCurrentSelection() return l and l[0] def getItem(self, index): if self.list: if len(self.list) > index: return self.list[index] and self.list[index][0] GUI_WIDGET = eListbox def postWidgetCreate(self, instance): instance.setContent(self.l) instance.selectionChanged.get().append(self.selectionChanged) self.setFontsize() def preWidgetRemove(self, instance): instance.setContent(None) instance.selectionChanged.get().remove(self.selectionChanged) def reload(self, root=None, filter_tags=None): if self.reloadDelayTimer is not None: self.reloadDelayTimer.stop() self.reloadDelayTimer = None if root is not None: self.load(root, filter_tags) else: self.load(self.root, filter_tags) self.l.setList(self.list) def removeService(self, service): index = self.findService(service) if index is not None: del self.list[index] self.l.setList(self.list) def findService(self, service): if service is None: return None for index, l in enumerate(self.list): if l[0] == service: return index return None def __len__(self): return len(self.list) def __getitem__(self, index): return self.list[index] def __iter__(self): return self.list.__iter__() def load(self, root, filter_tags): # this lists our root service, then building a # nice list del self.list[:] serviceHandler = eServiceCenter.getInstance() numberOfDirs = 0 reflist = root and serviceHandler.list(root) if reflist is None: print "listing of movies failed" return realtags = set() autotags = {} rootPath = os.path.normpath(root.getPath()) parent = None # Don't navigate above the "root" if len(rootPath) > 1 and (os.path.realpath(rootPath) != os.path.realpath( config.movielist.root.value)): parent = os.path.split(os.path.normpath(rootPath))[0] currentfolder = os.path.normpath(rootPath) + '/' if parent and (parent not in defaultInhibitDirs ) and not currentfolder.endswith( config.usage.default_path.value): # enigma wants an extra '/' appended if not parent.endswith('/'): parent += '/' ref = eServiceReference("2:0:1:0:0:0:0:0:0:0:" + parent) ref.flags = eServiceReference.flagDirectory self.list.append((ref, None, 0, -1)) numberOfDirs += 1 while 1: serviceref = reflist.getNext() if not serviceref.valid(): break if config.ParentalControl.servicepinactive.value and config.ParentalControl.storeservicepin.value != "never": from Components.ParentalControl import parentalControl if not parentalControl.sessionPinCached and parentalControl.isProtected( serviceref): continue info = serviceHandler.info(serviceref) if info is None: info = justStubInfo begin = info.getInfo(serviceref, iServiceInformation.sTimeCreate) if serviceref.flags & eServiceReference.mustDescent: dirname = info.getName(serviceref) if not dirname.endswith( '.AppleDouble/') and not dirname.endswith( '.AppleDesktop/') and not dirname.endswith( '.AppleDB/') and not dirname.endswith( 'Network Trash Folder/' ) and not dirname.endswith('Temporary Items/'): self.list.append((serviceref, info, begin, -1)) numberOfDirs += 1 continue # convert separe-separated list of tags into a set this_tags = info.getInfoString( serviceref, iServiceInformation.sTags).split(' ') name = info.getName(serviceref) # OSX put a lot of stupid files ._* everywhere... we need to skip them if name[:2] == "._": continue if this_tags == ['']: # No tags? Auto tag! this_tags = name.replace(',', ' ').replace('.', ' ').replace( '_', ' ').replace(':', ' ').split() # For auto tags, we are keeping a (tag, movies) dictionary. #It will be used later to check if movies have a complete sentence in common. for tag in this_tags: if autotags.has_key(tag): autotags[tag].append(name) else: autotags[tag] = [name] else: realtags.update(this_tags) # filter_tags is either None (which means no filter at all), or # a set. In this case, all elements of filter_tags must be present, # otherwise the entry will be dropped. if filter_tags is not None: this_tags_fullname = [" ".join(this_tags)] this_tags_fullname = set(this_tags_fullname) this_tags = set(this_tags) if not this_tags.issuperset( filter_tags) and not this_tags_fullname.issuperset( filter_tags): # print "Skipping", name, "tags=", this_tags, " filter=", filter_tags continue self.list.append((serviceref, info, begin, -1)) self.firstFileEntry = numberOfDirs self.parentDirectory = 0 self.list.sort(key=self.buildGroupwiseSortkey) if self.sort_type == MovieList.SORT_ALPHANUMERIC: self.list = sorted(self.list[:numberOfDirs], key=self.buildAlphaNumericSortKey) + sorted( self.list[numberOfDirs:], key=self.buildAlphaNumericSortKey) elif self.sort_type == MovieList.SORT_ALPHANUMERIC_REVERSE: self.list = sorted(self.list[:numberOfDirs], key=self.buildAlphaNumericSortKey, reverse=True) + sorted( self.list[numberOfDirs:], key=self.buildAlphaNumericSortKey, reverse=True) elif self.sort_type == MovieList.SORT_ALPHANUMERIC_FLAT: self.list.sort(key=self.buildAlphaNumericFlatSortKey) elif self.sort_type == MovieList.SORT_ALPHANUMERIC_FLAT_REVERSE: self.list.sort(key=self.buildAlphaNumericFlatSortKey, reverse=True) elif self.sort_type == MovieList.SORT_RECORDED: self.list = sorted(self.list[:numberOfDirs], key=self.buildBeginTimeSortKey) + sorted( self.list[numberOfDirs:], key=self.buildBeginTimeSortKey) elif self.sort_type == MovieList.SORT_RECORDED_REVERSE: self.list = sorted(self.list[:numberOfDirs], key=self.buildBeginTimeSortKey, reverse=True) + sorted( self.list[numberOfDirs:], key=self.buildBeginTimeSortKey, reverse=True) elif self.sort_type == MovieList.SHUFFLE: dirlist = self.list[:numberOfDirs] shufflelist = self.list[numberOfDirs:] random.shuffle(shufflelist) self.list = dirlist + shufflelist elif self.sort_type == MovieList.SORT_ALPHA_DATE_OLDEST_FIRST: self.list = sorted(self.list[:numberOfDirs], key=self.buildAlphaDateSortKey) + sorted( self.list[numberOfDirs:], key=self.buildAlphaDateSortKey) elif self.sort_type == MovieList.SORT_ALPHAREV_DATE_NEWEST_FIRST: self.list = sorted(self.list[:numberOfDirs], key=self.buildAlphaDateSortKey, reverse=True) + sorted( self.list[numberOfDirs:], key=self.buildAlphaDateSortKey, reverse=True) for x in self.list: if x[1]: tmppath = x[1].getName(x[0])[:-1] if x[1].getName( x[0]).endswith('/') else x[1].getName(x[0]) if tmppath.endswith('.Trash'): self.list.insert(0, self.list.pop(self.list.index(x))) break if self.root and numberOfDirs > 0: rootPath = os.path.normpath(self.root.getPath()) if not rootPath.endswith('/'): rootPath += '/' if rootPath != parent: # with new sort types directories may be in between files, so scan whole # list for parentDirectory index. Usually it is the first one anyway for index, item in enumerate(self.list): if item[0].flags & eServiceReference.mustDescent: itempath = os.path.normpath(item[0].getPath()) if not itempath.endswith('/'): itempath += '/' if itempath == rootPath: self.parentDirectory = index break self.root = root # finally, store a list of all tags which were found. these can be presented # to the user to filter the list # ML: Only use the tags that occur more than once in the list OR that were # really in the tag set of some file. # reverse the dictionary to see which unique movie each tag now references rautotags = {} for tag, movies in autotags.items(): if (len(movies) > 1): movies = tuple(movies) # a tuple can be hashed, but a list not item = rautotags.get(movies, []) if not item: rautotags[movies] = item item.append(tag) self.tags = {} for movies, tags in rautotags.items(): movie = movies[0] # format the tag lists so that they are in 'original' order tags.sort(key=movie.find) first = movie.find(tags[0]) last = movie.find(tags[-1]) + len(tags[-1]) match = movie start = 0 end = len(movie) # Check if the set has a complete sentence in common, and how far for m in movies[1:]: if m[start:end] != match: if not m.startswith(movie[:last]): start = first if not m.endswith(movie[first:]): end = last match = movie[start:end] if m[start:end] != match: match = '' break # Adding the longest common sentence to the tag list if match: self.tags[match] = set(tags) else: match = ' '.join(tags) if (len(match) > 2) or ( match in realtags): #Omit small words, only for auto tags self.tags[match] = set(tags) # Adding the realtags to the tag list for tag in realtags: self.tags[tag] = set([tag]) def buildAlphaNumericSortKey(self, x): # x = ref,info,begin,... ref = x[0] name = x[1] and x[1].getName(ref) if ref.flags & eServiceReference.mustDescent: return 0, name and name.lower() or "", -x[2] return 1, name and name.lower() or "", -x[2] # as for buildAlphaNumericSortKey, but without negating dates def buildAlphaDateSortKey(self, x): # x = ref,info,begin,... ref = x[0] name = x[1] and x[1].getName(ref) if ref.flags & eServiceReference.mustDescent: return 0, name and name.lower() or "", x[2] return 1, name and name.lower() or "", x[2] def buildAlphaNumericFlatSortKey(self, x): # x = ref,info,begin,... ref = x[0] name = x[1] and x[1].getName(ref) if name and ref.flags & eServiceReference.mustDescent: # only use directory basename for sorting p = os.path.split(name) if not p[1]: # if path ends in '/', p is blank. p = os.path.split(p[0]) name = p[1] # print "Sorting for -%s-" % name return 1, name and name.lower() or "", -x[2] def buildBeginTimeSortKey(self, x): ref = x[0] if ref.flags & eServiceReference.mustDescent: return 0, x[1] and -os.stat(ref.getPath()).st_mtime return 1, -x[2] def buildGroupwiseSortkey(self, x): # Sort recordings by date, sort MP3 and stuff by name ref = x[0] if ref.type >= eServiceReference.idUser: return self.buildAlphaNumericSortKey(x) else: return self.buildBeginTimeSortKey(x) def moveTo(self, serviceref): index = self.findService(serviceref) if index is not None: self.instance.moveSelectionTo(index) return True return False def moveDown(self): self.instance.moveSelection(self.instance.moveDown) def moveUp(self): self.instance.moveSelection(self.instance.moveUp) def moveToChar(self, char, lbl=None): self._char = char self._lbl = lbl if lbl: lbl.setText(self._char) lbl.visible = True self.moveToCharTimer = eTimer() self.moveToCharTimer.callback.append(self._moveToChrStr) self.moveToCharTimer.start( 1000, True ) #time to wait for next key press to decide which letter to use... def moveToString(self, char, lbl=None): self._char = self._char + char.upper() self._lbl = lbl if lbl: lbl.setText(self._char) lbl.visible = True self.moveToCharTimer = eTimer() self.moveToCharTimer.callback.append(self._moveToChrStr) self.moveToCharTimer.start( 1000, True ) #time to wait for next key press to decide which letter to use... def _moveToChrStr(self): currentIndex = self.instance.getCurrentIndex() found = False if currentIndex < (len(self.list) - 1): itemsBelow = self.list[currentIndex + 1:] #first search the items below the selection for index, item in enumerate(itemsBelow): ref = item[0] itemName = getShortName(item[1].getName(ref).upper(), ref) if len(self._char) == 1 and itemName.startswith(self._char): found = True self.instance.moveSelectionTo(index + currentIndex + 1) break elif len(self._char) > 1 and itemName.find(self._char) >= 0: found = True self.instance.moveSelectionTo(index + currentIndex + 1) break if found == False and currentIndex > 0: itemsAbove = self.list[ 1: currentIndex] #first item (0) points parent folder - no point to include for index, item in enumerate(itemsAbove): ref = item[0] itemName = getShortName(item[1].getName(ref).upper(), ref) if len(self._char) == 1 and itemName.startswith(self._char): found = True self.instance.moveSelectionTo(index + 1) break elif len(self._char) > 1 and itemName.find(self._char) >= 0: found = True self.instance.moveSelectionTo(index + 1) break self._char = '' if self._lbl: self._lbl.visible = False
class VirtualKeyBoard(Screen): def __init__(self, session, title="", **kwargs): Screen.__init__(self, session) self.setTitle(_(title)) self.keys_list = [] self.shiftkeys_list = [] self.lang = language.getLanguage() self.nextLang = None self.shiftMode = False self.selectedKey = 0 self.smsChar = None self.sms = NumericalTextInput(self.smsOK) self.key_bg = LoadPixmap(path=resolveFilename(SCOPE_ACTIVE_SKIN, "buttons/vkey_bg.png")) self.key_sel = LoadPixmap(path=resolveFilename(SCOPE_ACTIVE_SKIN, "buttons/vkey_sel.png")) self.key_backspace = LoadPixmap(path=resolveFilename(SCOPE_ACTIVE_SKIN, "buttons/vkey_backspace.png")) self.key_all = LoadPixmap(path=resolveFilename(SCOPE_ACTIVE_SKIN, "buttons/vkey_all.png")) self.key_clr = LoadPixmap(path=resolveFilename(SCOPE_ACTIVE_SKIN, "buttons/vkey_clr.png")) self.key_esc = LoadPixmap(path=resolveFilename(SCOPE_ACTIVE_SKIN, "buttons/vkey_esc.png")) self.key_ok = LoadPixmap(path=resolveFilename(SCOPE_ACTIVE_SKIN, "buttons/vkey_ok.png")) self.key_shift = LoadPixmap(path=resolveFilename(SCOPE_ACTIVE_SKIN, "buttons/vkey_shift.png")) self.key_shift_sel = LoadPixmap(path=resolveFilename(SCOPE_ACTIVE_SKIN, "buttons/vkey_shift_sel.png")) self.key_space = LoadPixmap(path=resolveFilename(SCOPE_ACTIVE_SKIN, "buttons/vkey_space.png")) self.key_left = LoadPixmap(path=resolveFilename(SCOPE_ACTIVE_SKIN, "buttons/vkey_left.png")) self.key_right = LoadPixmap(path=resolveFilename(SCOPE_ACTIVE_SKIN, "buttons/vkey_right.png")) self.keyImages = { "BACKSPACE": self.key_backspace, "ALL": self.key_all, "EXIT": self.key_esc, "OK": self.key_ok, "SHIFT": self.key_shift, "SPACE": self.key_space, "LEFT": self.key_left, "RIGHT": self.key_right } self.keyImagesShift = { "BACKSPACE": self.key_backspace, "CLEAR": self.key_clr, "EXIT": self.key_esc, "OK": self.key_ok, "SHIFT": self.key_shift_sel, "SPACE": self.key_space, "LEFT": self.key_left, "RIGHT": self.key_right } self["country"] = StaticText("") self["header"] = Label() self["text"] = Input(currPos=len(kwargs.get("text", "").decode("utf-8",'ignore')), allMarked=False, **kwargs) self["list"] = VirtualKeyBoardList([]) self["actions"] = NumberActionMap(["OkCancelActions", "WizardActions", "ColorActions", "KeyboardInputActions", "InputBoxActions", "InputAsciiActions"], { "gotAsciiCode": self.keyGotAscii, "ok": self.okClicked, "cancel": self.exit, "left": self.left, "right": self.right, "up": self.up, "down": self.down, "red": self.exit, "green": self.ok, "yellow": self.switchLang, "blue": self.shiftClicked, "deleteBackward": self.backClicked, "deleteForward": self.forwardClicked, "back": self.exit, "pageUp": self.cursorRight, "pageDown": self.cursorLeft, "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, }, -2) self.setLang() self.onExecBegin.append(self.setKeyboardModeAscii) self.onLayoutFinish.append(self.buildVirtualKeyBoard) self.onClose.append(self.__onClose) def __onClose(self): self.sms.timer.stop() def switchLang(self): self.lang = self.nextLang self.setLang() self.buildVirtualKeyBoard() def setLang(self): if self.lang == 'de_DE': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"ü", u"+"], [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ö", u"ä", u"#"], [u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL"], [u"SHIFT", u"SPACE", u"@", u"ß", u"OK", u"LEFT", u"RIGHT"]] self.shiftkeys_list = [ [u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE"], [u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"Ü", u"*"], [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"Ö", u"Ä", u"'"], [u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR"], [u"SHIFT", u"SPACE", u"?", u"\\", u"OK", u"LEFT", u"RIGHT"]] self.nextLang = 'es_ES' elif self.lang == 'es_ES': #still missing keys (u"ùÙ") self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"ú", u"+"], [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ó", u"á", u"#"], [u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL"], [u"SHIFT", u"SPACE", u"@", u"Ł", u"ŕ", u"é", u"č", u"í", u"ě", u"ń", u"ň", u"OK"]] self.shiftkeys_list = [ [u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE"], [u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"Ú", u"*"], [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"Ó", u"Á", u"'"], [u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR"], [u"SHIFT", u"SPACE", u"?", u"\\", u"Ŕ", u"É", u"Č", u"Í", u"Ě", u"Ń", u"Ň", u"OK"]] self.nextLang = 'fi_FI' elif self.lang == 'fi_FI': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"é", u"+"], [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ö", u"ä", u"#"], [u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL"], [u"SHIFT", u"SPACE", u"@", u"ß", u"ĺ", u"OK", u"LEFT", u"RIGHT"]] self.shiftkeys_list = [ [u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE"], [u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"É", u"*"], [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"Ö", u"Ä", u"'"], [u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR"], [u"SHIFT", u"SPACE", u"?", u"\\", u"Ĺ", u"OK", u"LEFT", u"RIGHT"]] self.nextLang = 'lv_LV' elif self.lang == 'lv_LV': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"q", u"w", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"-", u"š"], [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u";", u"'", u"ū"], [u"<", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", u".", u"ž", u"ALL"], [u"SHIFT", u"SPACE", u"ā", u"č", u"ē", u"ģ", u"ī", u"ķ", u"ļ", u"ņ", u"LEFT", u"RIGHT"]] self.shiftkeys_list = [ [u"EXIT", u"!", u"@", u"$", u"*", u"(", u")", u"_", u"=", u"/", u"\\", u"BACKSPACE"], [u"Q", u"W", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"+", u"Š"], [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u":", u'"', u"Ū"], [u">", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u"#", u"?", u"Ž", u"CLEAR"], [u"SHIFT", u"SPACE", u"Ā", u"Č", u"Ē", u"Ģ", u"Ī", u"Ķ", u"Ļ", u"Ņ", u"LEFT", u"RIGHT"]] self.nextLang = 'ru_RU' elif self.lang == 'ru_RU': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"а", u"б", u"в", u"г", u"д", u"е", u"ё", u"ж", u"з", u"и", u"й", u"+"], [u"к", u"л", u"м", u"н", u"о", u"п", u"р", u"с", u"т", u"у", u"ф", u"#"], [u"<", u"х", u"ц", u"ч", u"ш", u"щ", u"ъ", u"ы", u",", u".", u"-", u"ALL"], [u"SHIFT", u"SPACE", u"@", u"ь", u"э", u"ю", u"я", u"OK", u"LEFT", u"RIGHT"]] self.shiftkeys_list = [ [u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE"], [u"А", u"Б", u"В", u"Г", u"Д", u"Е", u"Ё", u"Ж", u"З", u"И", u"Й", u"*"], [u"К", u"Л", u"М", u"Н", u"О", u"П", u"Р", u"С", u"Т", u"У", u"Ф", u"'"], [u">", u"Х", u"Ц", u"Ч", u"Ш", u"Щ", u"Ъ", u"Ы", u";", u":", u"_", u"CLEAR"], [u"SHIFT", u"SPACE", u"?", u"\\", u"Ь", u"Э", u"Ю", u"Я", u"OK", u"LEFT", u"RIGHT"]] self.nextLang = 'sv_SE' elif self.lang == 'sv_SE': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"é", u"+"], [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ö", u"ä", u"#"], [u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL"], [u"SHIFT", u"SPACE", u"@", u"ß", u"ĺ", u"OK", u"LEFT", u"RIGHT"]] self.shiftkeys_list = [ [u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE"], [u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"É", u"*"], [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"Ö", u"Ä", u"'"], [u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR"], [u"SHIFT", u"SPACE", u"?", u"\\", u"Ĺ", u"OK", u"LEFT", u"RIGHT"]] self.nextLang = 'sk_SK' elif self.lang =='sk_SK': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"ú", u"+"], [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ľ", u"@", u"#"], [u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL"], [u"SHIFT", u"SPACE", u"š", u"č", u"ž", u"ý", u"á", u"í", u"é", u"OK", u"LEFT", u"RIGHT"]] self.shiftkeys_list = [ [u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE"], [u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"ť", u"*"], [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"ň", u"ď", u"'"], [u"Á", u"É", u"Ď", u"Í", u"Ý", u"Ó", u"Ú", u"Ž", u"Š", u"Č", u"Ť", u"Ň"], [u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR"], [u"SHIFT", u"SPACE", u"?", u"\\", u"ä", u"ö", u"ü", u"ô", u"ŕ", u"ĺ", u"OK"]] self.nextLang = 'cs_CZ' elif self.lang == 'cs_CZ': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"ú", u"+"], [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ů", u"@", u"#"], [u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL"], [u"SHIFT", u"SPACE", u"ě", u"š", u"č", u"ř", u"ž", u"ý", u"á", u"í", u"é", u"OK"]] self.shiftkeys_list = [ [u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE"], [u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"ť", u"*"], [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"ň", u"ď", u"'"], [u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR"], [u"SHIFT", u"SPACE", u"?", u"\\", u"Č", u"Ř", u"Š", u"Ž", u"Ú", u"Á", u"É", u"OK"]] self.nextLang = 'el_GR' elif self.lang == 'el_GR': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"=", u"ς", u"ε", u"ρ", u"τ", u"υ", u"θ", u"ι", u"ο", u"π", u"[", u"]"], [u"α", u"σ", u"δ", u"φ", u"γ", u"η", u"ξ", u"κ", u"λ", u";", u"'", u"-"], [u"\\", u"ζ", u"χ", u"ψ", u"ω", u"β", u"ν", u"μ", u",", ".", u"/", u"ALL"], [u"SHIFT", u"SPACE", u"ά", u"έ", u"ή", u"ί", u"ό", u"ύ", u"ώ", u"ϊ", u"ϋ", u"OK"]] self.shiftkeys_list = [ [u"EXIT", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"*", u"(", u")", u"BACKSPACE"], [u"+", u"€", u"Ε", u"Ρ", u"Τ", u"Υ", u"Θ", u"Ι", u"Ο", u"Π", u"{", u"}"], [u"Α", u"Σ", u"Δ", u"Φ", u"Γ", u"Η", u"Ξ", u"Κ", u"Λ", u":", u'"', u"_"], [u"|", u"Ζ", u"Χ", u"Ψ", u"Ω", u"Β", u"Ν", u"Μ", u"<", u">", u"?", u"CLEAR"], [u"SHIFT", u"SPACE", u"Ά", u"Έ", u"Ή", u"Ί", u"Ό", u"Ύ", u"Ώ", u"Ϊ", u"Ϋ", u"OK"]] self.nextLang = 'pl_PL' elif self.lang == 'pl_PL': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"q", u"w", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"-", u"["], [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u";", u"'", u"\\"], [u"<", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"/", u"ALL"], [u"SHIFT", u"SPACE", u"ą", u"ć", u"ę", u"ł", u"ń", u"ó", u"ś", u"ź", u"ż", u"OK"]] self.shiftkeys_list = [ [u"EXIT", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"(", u")", u"=", u"BACKSPACE"], [u"Q", u"W", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"*", u"]"], [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"?", u'"', u"|"], [u">", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR"], [u"SHIFT", u"SPACE", u"Ą", u"Ć", u"Ę", u"Ł", u"Ń", u"Ó", u"Ś", u"Ź", u"Ż", u"OK"]] self.nextLang = 'en_EN' else: self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"q", u"w", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"-", u"["], [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u";", u"'", u"\\"], [u"<", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"/", u"ALL"], [u"SHIFT", u"SPACE", u"OK", u"LEFT", u"RIGHT", u"*"]] self.shiftkeys_list = [ [u"EXIT", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"(", u")", u"=", u"BACKSPACE"], [u"Q", u"W", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"+", u"]"], [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"?", u'"', u"|"], [u">", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR"], [u"SHIFT", u"SPACE", u"OK", u"LEFT", u"RIGHT", u"~"]] self.lang = 'en_EN' self.nextLang = 'de_DE' self["country"].setText(self.lang) self.max_key=47+len(self.keys_list[4]) def virtualKeyBoardEntryComponent(self, keys): w, h = skin.parameters.get("VirtualKeyboard",(45, 45)) key_bg_width = self.key_bg and self.key_bg.size().width() or w key_images = self.shiftMode and self.keyImagesShift or self.keyImages res = [keys] text = [] x = 0 for key in keys: png = key_images.get(key, None) if png: width = png.size().width() res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, h), png=png)) else: width = key_bg_width res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, h), png=self.key_bg)) text.append(MultiContentEntryText(pos=(x, 0), size=(width, h), font=0, text=key.encode("utf-8"), flags=RT_HALIGN_CENTER | RT_VALIGN_CENTER)) x += width return res + text def buildVirtualKeyBoard(self): self.previousSelectedKey = None self.list = [] for keys in self.shiftMode and self.shiftkeys_list or self.keys_list: self.list.append(self.virtualKeyBoardEntryComponent(keys)) self.markSelectedKey() def markSelectedKey(self): w, h = skin.parameters.get("VirtualKeyboard",(45, 45)) if self.previousSelectedKey is not None: self.list[self.previousSelectedKey /12] = self.list[self.previousSelectedKey /12][:-1] width = self.key_sel.size().width() x = self.list[self.selectedKey/12][self.selectedKey % 12 + 1][1] self.list[self.selectedKey / 12].append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, h), png=self.key_sel)) self.previousSelectedKey = self.selectedKey self["list"].setList(self.list) def backClicked(self): self["text"].deleteBackward() def forwardClicked(self): self["text"].deleteForward() def shiftClicked(self): self.smsChar = None self.shiftMode = not self.shiftMode self.buildVirtualKeyBoard() def okClicked(self): self.smsChar = None text = (self.shiftMode and self.shiftkeys_list or self.keys_list)[self.selectedKey / 12][self.selectedKey % 12].encode("UTF-8") if text == "EXIT": self.close(None) elif text == "BACKSPACE": self["text"].deleteBackward() elif text == "ALL": self["text"].markAll() elif text == "CLEAR": self["text"].deleteAllChars() self["text"].update() elif text == "SHIFT": self.shiftClicked() elif text == "SPACE": self["text"].char(" ".encode("UTF-8")) elif text == "OK": self.close(self["text"].getText()) elif text == "LEFT": self["text"].left() elif text == "RIGHT": self["text"].right() else: self["text"].char(text) def ok(self): self.close(self["text"].getText()) def exit(self): self.close(None) def cursorRight(self): self["text"].right() def cursorLeft(self): self["text"].left() def left(self): self.smsChar = None self.selectedKey = self.selectedKey / 12 * 12 + (self.selectedKey + 11) % 12 if self.selectedKey > self.max_key: self.selectedKey = self.max_key self.markSelectedKey() def right(self): self.smsChar = None self.selectedKey = self.selectedKey / 12 * 12 + (self.selectedKey + 1) % 12 if self.selectedKey > self.max_key: self.selectedKey = self.selectedKey / 12 * 12 self.markSelectedKey() def up(self): self.smsChar = None self.selectedKey -= 12 if self.selectedKey < 0: self.selectedKey = self.max_key / 12 * 12 + self.selectedKey % 12 if self.selectedKey > self.max_key: self.selectedKey -= 12 self.markSelectedKey() def down(self): self.smsChar = None self.selectedKey += 12 if self.selectedKey > self.max_key: self.selectedKey %= 12 self.markSelectedKey() def keyNumberGlobal(self, number): self.smsChar = self.sms.getKey(number) self.selectAsciiKey(self.smsChar) def smsOK(self): if self.smsChar and self.selectAsciiKey(self.smsChar): print "[VirtualKeyboard] pressing ok now" self.okClicked() def keyGotAscii(self): self.smsChar = None if self.selectAsciiKey(str(unichr(getPrevAsciiCode()).encode('utf-8'))): self.okClicked() def selectAsciiKey(self, char): if char == " ": char = "SPACE" for keyslist in (self.shiftkeys_list, self.keys_list): selkey = 0 for keys in keyslist: for key in keys: if key == char: self.selectedKey = selkey if self.shiftMode != (keyslist is self.shiftkeys_list): self.shiftMode = not self.shiftMode self.buildVirtualKeyBoard() else: self.markSelectedKey() return True selkey += 1 return False
def VirtualKeyBoardEntryComponent(keys, selectedKey, shiftMode=False): key_backspace = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "vkey_backspace.png")) key_bg = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "vkey_bg.png")) key_clr = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "vkey_clr.png")) key_esc = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "vkey_esc.png")) key_ok = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "vkey_ok.png")) key_sel = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "vkey_sel.png")) key_shift = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "vkey_shift.png")) key_shift_sel = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "vkey_shift_sel.png")) key_space = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "vkey_space.png")) res = [(keys)] x = 0 count = 0 if shiftMode: shiftkey_png = key_shift_sel else: shiftkey_png = key_shift for key in keys: width = None if key == "EXIT": width = key_esc.size().width() res.append( MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=key_esc)) elif key == "BACKSPACE": width = key_backspace.size().width() res.append( MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=key_backspace)) elif key == "CLEAR": width = key_clr.size().width() res.append( MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=key_clr)) elif key == "SHIFT": width = shiftkey_png.size().width() res.append( MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=shiftkey_png)) elif key == "SPACE": width = key_space.size().width() res.append( MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=key_space)) elif key == "OK": width = key_ok.size().width() res.append( MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=key_ok)) #elif key == "<-": # res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(45, 45), png=key_left)) #elif key == "->": # res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(45, 45), png=key_right)) else: width = key_bg.size().width() res.extend((MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=key_bg), MultiContentEntryText(pos=(x, 0), size=(width, 45), font=0, text=key.encode("utf-8"), flags=RT_HALIGN_CENTER | RT_VALIGN_CENTER))) if selectedKey == count: width = key_sel.size().width() res.append( MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=key_sel)) if width is not None: x += width else: x += 45 count += 1 return res
class MovieList(GUIComponent): SORT_ALPHANUMERIC = 1 SORT_RECORDED = 2 SORT_SHUFFLE = 3 SORT_ALPHANUMERIC_REVERSE = 4 SORT_RECORDED_REVERSE = 5 SORT_ALPHANUMERIC_FLAT = 6 SORT_ALPHANUMERIC_FLAT_REVERSE = 7 SORT_GROUPWISE = 8 SORT_ALPHA_DATE_OLDEST_FIRST = 9 SORT_ALPHAREV_DATE_NEWEST_FIRST = 10 SORT_DURATION_ALPHA = 11 SORT_DURATIONREV_ALPHA = 12 SORT_SIZE_ALPHA = 13 SORT_SIZEREV_ALPHA = 14 SORT_DESCRIPTION_ALPHA = 15 HIDE_DESCRIPTION = 1 SHOW_DESCRIPTION = 2 # So MovieSelection.selectSortby() can find out whether we are # in a Trash folder and, if so, what the last sort was # The numbering starts after SORT_* values above. # in MovieSelection.py (that has no SORT_GROUPWISE) # NOTE! that these two *must* *follow on* from the end of the # SORT_* items above! # TRASHSORT_SHOWRECORD = 16 TRASHSORT_SHOWDELETE = 17 UsingTrashSort = False InTrashFolder = False def __init__(self, root, sort_type=None, descr_state=None): GUIComponent.__init__(self) self.list = [] self.descr_state = descr_state or self.HIDE_DESCRIPTION self.sort_type = sort_type or self.SORT_GROUPWISE self.firstFileEntry = 0 self.parentDirectory = 0 self.fontName = "Regular" self.fontSize = 20 self.listHeight = None self.listWidth = None self.pbarShift = 0 self.pbarHeight = 16 self.pbarLargeWidth = 48 self.pbarColour = 0x206333 self.pbarColourSeen = 0xffc71d self.pbarColourRec = 0xff001d self.partIconeShift = 0 self.spaceRight = 2 self.spaceIconeText = 2 self.iconsWidth = 22 self.durationWidth = 160 self.dateWidth = 160 if config.usage.time.wide.value: self.dateWidth = int(self.dateWidth * 1.15) self.reloadDelayTimer = None self.l = eListboxPythonMultiContent() self.tags = set() self.root = None self._playInBackground = None self._playInForeground = None self._char = '' if root is not None: self.reload(root) self.onSelectionChanged = [] self.iconPart = [] for part in range(5): self.iconPart.append( LoadPixmap( resolveFilename(SCOPE_GUISKIN, "icons/part_%d_4.png" % part))) self.iconMovieRec = LoadPixmap( resolveFilename(SCOPE_GUISKIN, "icons/part_new.png")) self.iconMoviePlay = LoadPixmap( resolveFilename(SCOPE_GUISKIN, "icons/movie_play.png")) self.iconMoviePlayRec = LoadPixmap( resolveFilename(SCOPE_GUISKIN, "icons/movie_play_rec.png")) self.iconUnwatched = LoadPixmap( resolveFilename(SCOPE_GUISKIN, "icons/part_unwatched.png")) self.iconFolder = LoadPixmap( resolveFilename(SCOPE_GUISKIN, "icons/folder.png")) self.iconTrash = LoadPixmap( resolveFilename(SCOPE_GUISKIN, "icons/trashcan.png")) self.iconCutting = LoadPixmap( resolveFilename(SCOPE_GUISKIN, "icons/cutting.png")) self.runningTimers = {} self.updateRecordings() def get_playInBackground(self): return self._playInBackground def set_playInBackground(self, value): if self._playInBackground is not value: index = self.findService(self._playInBackground) if index is not None: self.invalidateItem(index) self.l.invalidateEntry(index) index = self.findService(value) if index is not None: self.invalidateItem(index) self.l.invalidateEntry(index) self._playInBackground = value playInBackground = property(get_playInBackground, set_playInBackground) def get_playInForeground(self): return self._playInForeground def set_playInForeground(self, value): self._playInForeground = value playInForeground = property(get_playInForeground, set_playInForeground) def updateRecordings(self, timer=None): if timer is not None: if timer.justplay: return result = {} for timer in NavigationInstance.instance.RecordTimer.timer_list: if timer.isRunning() and not timer.justplay: result[os.path.split(timer.Filename)[1] + timer.record_service.getFilenameExtension()] = timer if self.runningTimers == result: return self.runningTimers = result if timer is not None: if self.reloadDelayTimer is not None: self.reloadDelayTimer.stop() self.reloadDelayTimer = eTimer() self.reloadDelayTimer.callback.append(self.reload) self.reloadDelayTimer.start(5000, 1) def connectSelChanged(self, fnc): if not fnc in self.onSelectionChanged: self.onSelectionChanged.append(fnc) def disconnectSelChanged(self, fnc): if fnc in self.onSelectionChanged: self.onSelectionChanged.remove(fnc) def selectionChanged(self): for x in self.onSelectionChanged: x() def setDescriptionState(self, val): self.descr_state = val def setSortType(self, type): self.sort_type = type def applySkin(self, desktop, parent): def warningWrongSkinParameter(string): print("[MovieList] wrong '%s' skin parameters" % string) def font(value): font = skin.parseFont(value, ((1, 1), (1, 1))) self.fontName = font.family self.fontSize = font.pointSize def partIconeShift(value): self.partIconeShift = int(value) def pbarShift(value): self.pbarShift = int(value) def pbarHeight(value): self.pbarHeight = int(value) def pbarLargeWidth(value): self.pbarLargeWidth = int(value) def pbarColour(value): self.pbarColour = skin.parseColor(value).argb() def pbarColourSeen(value): self.pbarColourSeen = skin.parseColor(value).argb() def pbarColourRec(value): self.pbarColourRec = skin.parseColor(value).argb() def spaceIconeText(value): self.spaceIconeText = int(value) def iconsWidth(value): self.iconsWidth = int(value) def trashShift(value): self.trashShift = int(value) def dirShift(value): self.dirShift = int(value) def spaceRight(value): self.spaceRight = int(value) def durationWidth(value): self.durationWidth = int(value) def dateWidth(value): self.dateWidth = int(value) if config.usage.time.wide.value: self.dateWidth = int(self.dateWidth * 1.15) for (attrib, value) in self.skinAttributes[:]: try: locals().get(attrib)(value) self.skinAttributes.remove((attrib, value)) except: pass rc = GUIComponent.applySkin(self, desktop, parent) self.listHeight = self.instance.size().height() self.listWidth = self.instance.size().width() self.setFontsize() self.setItemsPerPage() return rc def invalidateItem(self, index): x = self.list[index] self.list[index] = (x[0], x[1], x[2], None) def invalidateCurrentItem(self): self.invalidateItem(self.getCurrentIndex()) def setItemsPerPage(self): if self.listHeight > 0: itemHeight = self.listHeight / config.movielist.itemsperpage.value else: itemHeight = 15 # some default (270/5) self.itemHeight = itemHeight self.l.setItemHeight(itemHeight) self.instance.resize( eSize(self.listWidth, self.listHeight / itemHeight * itemHeight)) def setFontsize(self): if isHD(): self.l.setFont( 0, gFont(self.fontName, self.fontSize + config.movielist.fontsize.value)) self.l.setFont( 1, gFont(self.fontName, self.fontSize + config.movielist.fontsize.value)) else: self.l.setFont( 0, gFont(self.fontName, self.fontSize + config.movielist.fontsize.value + 10)) self.l.setFont( 1, gFont(self.fontName, self.fontSize + config.movielist.fontsize.value + 7)) def buildMovieListEntry(self, serviceref, info, begin, data): showPicons = "picon" in config.usage.movielist_servicename_mode.value switch = config.usage.show_icons_in_movielist.value piconWidth = config.usage.movielist_piconwidth.value if showPicons else 0 durationWidth = self.durationWidth if config.usage.load_length_of_movies_in_moviellist.value else 0 width = self.l.getItemSize().width() dateWidth = self.dateWidth if not config.movielist.use_fuzzy_dates.value: dateWidth += 30 iconSize = self.iconsWidth if switch == 'p': iconSize = self.pbarLargeWidth ih = self.itemHeight col0iconSize = piconWidth if showPicons else iconSize space = self.spaceIconeText r = self.spaceRight pathName = serviceref.getPath() res = [None] if serviceref.flags & eServiceReference.mustDescent: # Directory # Name is full path name if info is None: # Special case: "parent" txt = ".." else: p = os.path.split(pathName) if not p[1]: # if path ends in '/', p is blank. p = os.path.split(p[0]) txt = p[1] if txt == ".Trash": res.append( MultiContentEntryPixmapAlphaTest( pos=((col0iconSize - self.iconTrash.size().width()) / 2, (self.itemHeight - self.iconFolder.size().height()) / 2), size=(iconSize, self.iconTrash.size().height()), png=self.iconTrash)) res.append( MultiContentEntryText( pos=(col0iconSize + space, 0), size=(width - 145, self.itemHeight), font=0, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER, text=_("Deleted items"))) res.append( MultiContentEntryText(pos=(width - 185 - r, 0), size=(185, self.itemHeight), font=1, flags=RT_HALIGN_RIGHT | RT_VALIGN_CENTER, text=_("Trash can"))) return res if not config.movielist.show_underlines.value: txt = txt.replace('_', ' ').strip() res.append( MultiContentEntryPixmapAlphaTest( pos=((col0iconSize - self.iconFolder.size().width()) / 2, (self.itemHeight - self.iconFolder.size().height()) / 2), size=(iconSize, iconSize), png=self.iconFolder)) res.append( MultiContentEntryText(pos=(col0iconSize + space, 0), size=(width - 145, self.itemHeight), font=0, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER, text=txt)) res.append( MultiContentEntryText(pos=(width - 145 - r, 0), size=(145, self.itemHeight), font=1, flags=RT_HALIGN_RIGHT | RT_VALIGN_CENTER, text=_("Directory"))) return res if data == -1 or data is None: data = MovieListData() cur_idx = self.l.getCurrentSelectionIndex() x = self.list[cur_idx] # x = ref,info,begin,... if config.usage.load_length_of_movies_in_moviellist.value: data.len = x[1].getLength(x[0]) #recalc the movie length... else: data.len = 0 #dont recalc movielist to speedup loading the list self.list[cur_idx] = ( x[0], x[1], x[2], data ) #update entry in list... so next time we don't need to recalc if config.movielist.show_underlines.value: data.txt = info.getName(serviceref) else: data.txt = info.getName(serviceref).replace('_', ' ').strip() if config.movielist.hide_extensions.value: fileName, fileExtension = os.path.splitext(data.txt) if fileExtension in KNOWN_EXTENSIONS: data.txt = fileName data.icon = None data.part = None if os.path.split(pathName)[1] in self.runningTimers: if switch == 'i': if (self.playInBackground or self.playInForeground ) and serviceref == (self.playInBackground or self.playInForeground): data.icon = self.iconMoviePlayRec else: data.icon = self.iconMovieRec elif switch in ('p', 's'): data.part = 100 if (self.playInBackground or self.playInForeground ) and serviceref == (self.playInBackground or self.playInForeground): data.partcol = self.pbarColourSeen else: data.partcol = self.pbarColourRec elif (self.playInBackground or self.playInForeground) and serviceref == ( self.playInBackground or self.playInForeground): data.icon = self.iconMoviePlay elif pathName.endswith( ".tmpcut.ts" ): # cutting with moviecut plugin to same filename data.icon = self.iconCutting else: data.part = moviePlayState(pathName + '.cuts', serviceref, data.len) if switch == 'i': if data.part is not None and data.part > 0: data.icon = self.iconPart[data.part // 25] else: if config.usage.movielist_unseen.value: data.icon = self.iconUnwatched elif switch in ('p', 's'): if data.part is not None and data.part > 0: data.partcol = self.pbarColourSeen else: if config.usage.movielist_unseen.value: data.part = 100 data.partcol = self.pbarColour colX = 0 if switch == 'p': iconSize = self.pbarLargeWidth ih = self.itemHeight def addProgress(): # icon/progress if data: if switch == 'i' and hasattr(data, 'icon') and data.icon is not None: res.append( MultiContentEntryPixmapAlphaTest( pos=(colX, self.partIconeShift), size=(iconSize, data.icon.size().height()), png=data.icon)) elif switch in ('p', 's'): if hasattr(data, 'part') and data.part > 0: res.append( MultiContentEntryProgress(pos=(colX, self.pbarShift), size=(iconSize, self.pbarHeight), percent=data.part, borderWidth=2, foreColor=data.partcol, foreColorSelected=None, backColor=None, backColorSelected=None)) elif hasattr(data, 'icon') and data.icon is not None: res.append( MultiContentEntryPixmapAlphaTest( pos=(colX, self.pbarShift), size=(iconSize, self.pbarHeight), png=data.icon)) return iconSize serviceref = info.getInfoString(serviceref, iServiceInformation.sServiceref) displayPicon = None if piconWidth > 0: # Picon picon = getPiconName(serviceref) if picon != "": displayPicon = loadPNG(picon) if displayPicon is not None: res.append( MultiContentEntryPixmapAlphaTest( pos=(colX, 0), size=(piconWidth, ih), png=displayPicon, backcolor=None, backcolor_sel=None, flags=BT_SCALE | BT_KEEP_ASPECT_RATIO | BT_HALIGN_CENTER | BT_VALIGN_CENTER)) colX = piconWidth else: colX = addProgress() # Recording name res.append( MultiContentEntryText(pos=(colX, 0), size=(width - iconSize - space - durationWidth - dateWidth - r - colX, ih), font=0, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER, text=data.txt)) colX = width - iconSize - space - durationWidth - dateWidth - r if piconWidth > 0: colX = addProgress() # Duration Mins if durationWidth > 0: if data: len = data.len if len > 0: len = ngettext("%d Min", "%d Mins", (len / 60)) % (len / 60) res.append( MultiContentEntryText(pos=(colX + 880, 2), size=(durationWidth, ih), font=1, flags=RT_HALIGN_RIGHT | RT_VALIGN_CENTER, text=len)) # Date begin_string = "" if begin > 0: if config.movielist.use_fuzzy_dates.value: begin_string = ', '.join(FuzzyTime(begin, inPast=True)) else: begin_string = strftime( "%s, %s" % (config.usage.date.daylong.value, config.usage.time.short.value), localtime(begin)) res.append( MultiContentEntryText(pos=(width - dateWidth - r - 130, 2), size=(dateWidth + 130, ih), font=1, flags=RT_HALIGN_RIGHT | RT_VALIGN_CENTER, text=begin_string)) return res def moveToFirstMovie(self): if self.firstFileEntry < len(self.list): self.instance.moveSelectionTo(self.firstFileEntry) else: # there are no movies, just directories... self.moveToFirst() def moveToParentDirectory(self): if self.parentDirectory < len(self.list): self.instance.moveSelectionTo(self.parentDirectory) else: self.moveToFirst() def moveToLast(self): if self.list: self.instance.moveSelectionTo(len(self.list) - 1) def moveToFirst(self): if self.list: self.instance.moveSelectionTo(0) def moveToIndex(self, index): self.instance.moveSelectionTo(index) def getCurrentIndex(self): return self.instance.getCurrentIndex() def getCurrentEvent(self): l = self.l.getCurrentSelection() return l and l[0] and l[1] and l[1].getEvent(l[0]) def getCurrent(self): l = self.l.getCurrentSelection() return l and l[0] def getItem(self, index): if self.list: if len(self.list) > index: return self.list[index] and self.list[index][0] GUI_WIDGET = eListbox def postWidgetCreate(self, instance): instance.setContent(self.l) instance.selectionChanged.get().append(self.selectionChanged) self.setFontsize() def preWidgetRemove(self, instance): instance.setContent(None) instance.selectionChanged.get().remove(self.selectionChanged) def reload(self, root=None, filter_tags=None): if self.reloadDelayTimer is not None: self.reloadDelayTimer.stop() self.reloadDelayTimer = None if root is not None: self.load(root, filter_tags) else: self.load(self.root, filter_tags) self.l.setBuildFunc( self.buildMovieListEntry ) # don't move that to __init__ as this will create memory leak when calling MovieList from WebIf self.l.setList(self.list) def removeService(self, service): index = self.findService(service) if index is not None: del self.list[index] self.l.setList(self.list) def findService(self, service): if service is None: return None for index, l in enumerate(self.list): if l[0] == service: return index return None def __len__(self): return len(self.list) def __getitem__(self, index): return self.list[index] def __iter__(self): return self.list.__iter__() def load(self, root, filter_tags): # this lists our root service, then building a # nice list del self.list[:] serviceHandler = eServiceCenter.getInstance() numberOfDirs = 0 reflist = root and serviceHandler.list(root) if reflist is None: print("[MovieList] listing of movies failed") return realtags = set() autotags = {} rootPath = os.path.normpath(root.getPath()) parent = None # Don't navigate above the "root" if len(rootPath) > 1 and (os.path.realpath(rootPath) != os.path.realpath( config.movielist.root.value)): parent = os.path.split(os.path.normpath(rootPath))[0] if parent and (parent not in defaultInhibitDirs): # enigma wants an extra '/' appended if not parent.endswith('/'): parent += '/' ref = eServiceReference("2:0:1:0:0:0:0:0:0:0:" + parent) ref.flags = eServiceReference.flagDirectory self.list.append((ref, None, 0, -1)) numberOfDirs += 1 if config.usage.movielist_trashcan.value: here = os.path.realpath(rootPath) MovieList.InTrashFolder = here.startswith(getTrashFolder(here)) else: MovieList.InTrashFolder = False MovieList.UsingTrashSort = False if MovieList.InTrashFolder: if (config.usage.trashsort_deltime.value == "show record time"): MovieList.UsingTrashSort = MovieList.TRASHSORT_SHOWRECORD elif (config.usage.trashsort_deltime.value == "show delete time"): MovieList.UsingTrashSort = MovieList.TRASHSORT_SHOWDELETE while True: serviceref = reflist.getNext() if not serviceref.valid(): break if config.ParentalControl.servicepinactive.value and config.ParentalControl.storeservicepin.value != "never": from Components.ParentalControl import parentalControl if not parentalControl.sessionPinCached and parentalControl.isProtected( serviceref): continue info = serviceHandler.info(serviceref) if info is None: info = justStubInfo begin = info.getInfo(serviceref, iServiceInformation.sTimeCreate) begin2 = 0 if MovieList.UsingTrashSort: f_path = serviceref.getPath() if os.path.exists(f_path): # Override with deltime for sorting if MovieList.UsingTrashSort == MovieList.TRASHSORT_SHOWRECORD: begin2 = begin # Save for later re-instatement begin = os.stat(f_path).st_ctime if serviceref.flags & eServiceReference.mustDescent: dirname = info.getName(serviceref) if not dirname.endswith( '.AppleDouble/') and not dirname.endswith( '.AppleDesktop/') and not dirname.endswith( '.AppleDB/') and not dirname.endswith( 'Network Trash Folder/' ) and not dirname.endswith('Temporary Items/'): self.list.append((serviceref, info, begin, -1)) numberOfDirs += 1 continue # convert space-separated list of tags into a set this_tags = info.getInfoString( serviceref, iServiceInformation.sTags).split(' ') name = info.getName(serviceref) # OSX put a lot of stupid files ._* everywhere... we need to skip them if name[:2] == "._": continue if this_tags == ['']: # No tags? Auto tag! this_tags = name.replace(',', ' ').replace('.', ' ').replace( '_', ' ').replace(':', ' ').split() # For auto tags, we are keeping a (tag, movies) dictionary. #It will be used later to check if movies have a complete sentence in common. for tag in this_tags: if tag in autotags: autotags[tag].append(name) else: autotags[tag] = [name] else: realtags.update(this_tags) # filter_tags is either None (which means no filter at all), or # a set. In this case, all elements of filter_tags must be present, # otherwise the entry will be dropped. if filter_tags is not None: this_tags_fullname = [" ".join(this_tags)] this_tags_fullname = set(this_tags_fullname) this_tags = set(this_tags) if not this_tags.issuperset( filter_tags) and not this_tags_fullname.issuperset( filter_tags): # print("Skipping", name, "tags=", this_tags, " filter=", filter_tags) continue if begin2 != 0: self.list.append((serviceref, info, begin, -1, begin2)) else: self.list.append((serviceref, info, begin, -1)) self.firstFileEntry = numberOfDirs self.parentDirectory = 0 self.list.sort(key=self.buildGroupwiseSortkey) # Have we had a temporary sort method override set in MovieSelectiom.py? # If so use it, remove it (it's a one-off) and set the current method so # that the "Sort by" menu can highlight it and "Sort" knows which to # move on from (both in Screens/MovieSelection.py). # try: self.current_sort = self.temp_sort del self.temp_sort except: self.current_sort = self.sort_type if MovieList.UsingTrashSort: # Same as SORT_RECORDED, but must come first... self.list = sorted(self.list[:numberOfDirs], key=self.buildBeginTimeSortKey) + sorted( self.list[numberOfDirs:], key=self.buildBeginTimeSortKey) # Having sorted on *deletion* times, re-instate any record times for # *display* if that option is set. # self.list is a list of tuples, so we can't just assign to elements... # if config.usage.trashsort_deltime.value == "show record time": for i in range(len(self.list)): if len(self.list[i]) == 5: x = self.list[i] self.list[i] = (x[0], x[1], x[4], x[3]) elif self.current_sort == MovieList.SORT_ALPHANUMERIC: self.list = sorted(self.list[:numberOfDirs], key=self.buildAlphaNumericSortKey) + sorted( self.list[numberOfDirs:], key=self.buildAlphaNumericSortKey) elif self.current_sort == MovieList.SORT_ALPHANUMERIC_REVERSE: self.list = sorted(self.list[:numberOfDirs], key=self.buildAlphaNumericSortKey, reverse=True) + sorted( self.list[numberOfDirs:], key=self.buildAlphaNumericSortKey, reverse=True) elif self.current_sort == MovieList.SORT_ALPHANUMERIC_FLAT: self.list.sort(key=self.buildAlphaNumericFlatSortKey) elif self.current_sort == MovieList.SORT_ALPHANUMERIC_FLAT_REVERSE: self.list.sort(key=self.buildAlphaNumericFlatSortKey, reverse=True) elif self.current_sort == MovieList.SORT_RECORDED: self.list = sorted(self.list[:numberOfDirs], key=self.buildBeginTimeSortKey) + sorted( self.list[numberOfDirs:], key=self.buildBeginTimeSortKey) elif self.current_sort == MovieList.SORT_RECORDED_REVERSE: self.list = sorted(self.list[:numberOfDirs], key=self.buildBeginTimeSortKey, reverse=True) + sorted( self.list[numberOfDirs:], key=self.buildBeginTimeSortKey, reverse=True) elif self.current_sort == MovieList.SORT_SHUFFLE: dirlist = self.list[:numberOfDirs] shufflelist = self.list[numberOfDirs:] random.shuffle(shufflelist) self.list = dirlist + shufflelist elif self.current_sort == MovieList.SORT_ALPHA_DATE_OLDEST_FIRST: self.list = sorted(self.list[:numberOfDirs], key=self.buildAlphaDateSortKey) + sorted( self.list[numberOfDirs:], key=self.buildAlphaDateSortKey) elif self.current_sort == MovieList.SORT_ALPHAREV_DATE_NEWEST_FIRST: self.list = sorted(self.list[:numberOfDirs], key=self.buildAlphaDateSortKey, reverse=True) + sorted( self.list[numberOfDirs:], key=self.buildAlphaDateSortKey, reverse=True) elif self.sort_type == MovieList.SORT_DURATION_ALPHA: self.list = sorted(self.list[:numberOfDirs], key=self.buildAlphaDateSortKey) + sorted( self.list[numberOfDirs:], key=self.buildLengthAlphaSortKey) elif self.sort_type == MovieList.SORT_DURATIONREV_ALPHA: self.list = sorted(self.list[:numberOfDirs], key=self.buildAlphaDateSortKey) + sorted( self.list[numberOfDirs:], key=self.buildLengthRevAlphaSortKey) elif self.sort_type == MovieList.SORT_SIZE_ALPHA: self.list = sorted(self.list[:numberOfDirs], key=self.buildAlphaDateSortKey) + sorted( self.list[numberOfDirs:], key=self.buildSizeAlphaSortKey) elif self.sort_type == MovieList.SORT_SIZEREV_ALPHA: self.list = sorted(self.list[:numberOfDirs], key=self.buildAlphaDateSortKey) + sorted( self.list[numberOfDirs:], key=self.buildSizeRevAlphaSortKey) elif self.sort_type == MovieList.SORT_DESCRIPTION_ALPHA: self.list = sorted(self.list[:numberOfDirs], key=self.buildDescrAlphaSortKey) + sorted( self.list[numberOfDirs:], key=self.buildDescrAlphaSortKey) else: self.list.sort(key=self.buildGroupwiseSortkey) for x in self.list: if x[1]: tmppath = x[1].getName(x[0])[:-1] if x[1].getName( x[0]).endswith('/') else x[1].getName(x[0]) if tmppath.endswith('.Trash'): self.list.insert(0, self.list.pop(self.list.index(x))) break if self.root and numberOfDirs > 0: rootPath = os.path.normpath(self.root.getPath()) if not rootPath.endswith('/'): rootPath += '/' if rootPath != parent: # with new sort types directories may be in between files, so scan whole # list for parentDirectory index. Usually it is the first one anyway for index, item in enumerate(self.list): if item[0].flags & eServiceReference.mustDescent: itempath = os.path.normpath(item[0].getPath()) if not itempath.endswith('/'): itempath += '/' if itempath == rootPath: self.parentDirectory = index break self.root = root # finally, store a list of all tags which were found. these can be presented # to the user to filter the list # ML: Only use the tags that occur more than once in the list OR that were # really in the tag set of some file. # reverse the dictionary to see which unique movie each tag now references rautotags = {} for tag, movies in autotags.items(): if (len(movies) > 1): movies = tuple(movies) # a tuple can be hashed, but a list not item = rautotags.get(movies, []) if not item: rautotags[movies] = item item.append(tag) self.tags = {} for movies, tags in rautotags.items(): movie = movies[0] # format the tag lists so that they are in 'original' order tags.sort(key=movie.find) first = movie.find(tags[0]) last = movie.find(tags[-1]) + len(tags[-1]) match = movie start = 0 end = len(movie) # Check if the set has a complete sentence in common, and how far for m in movies[1:]: if m[start:end] != match: if not m.startswith(movie[:last]): start = first if not m.endswith(movie[first:]): end = last match = movie[start:end] if m[start:end] != match: match = '' break # Adding the longest common sentence to the tag list if match: self.tags[match] = set(tags) else: match = ' '.join(tags) if (len(match) > 2) or ( match in realtags): #Omit small words, only for auto tags self.tags[match] = set(tags) # Adding the realtags to the tag list for tag in realtags: self.tags[tag] = set([tag]) def getNameKey(self, ref, info): # Append the file name numeric suffix to the name, to reliably # sort recordings that have been split. name = info and info.getName(ref) if name: path = ref.getPath() if path.endswith(".ts") and path[-7] == "_": name += path[-6:-3] return name and name.lower() or "" def buildAlphaDateSortKey(self, x): # x = ref,info,begin,... ref = x[0] name = self.getNameKey(ref, x[1]) if ref.flags & eServiceReference.mustDescent: return (0, name, x[2]) return (1, name, x[2]) def buildAlphaNumericFlatSortKey(self, x): # x = ref,info,begin,... ref = x[0] name = self.getNameKey(ref, x[1]) or ".." if ref.flags & eServiceReference.mustDescent: # Only use directory basename for sorting. try: name = os.path.basename(os.path.normpath(name)) except (IOError, OSError) as err: pass # print("[MovieList] Sorting for -%s-" % name) return (1, name, -x[2]) def buildAlphaNumericSortKey(self, x): # x = ref,info,begin,... ref = x[0] name = self.getNameKey(ref, x[1]) if ref.flags & eServiceReference.mustDescent: return (0, name, -x[2]) return (1, name, -x[2]) def buildBeginTimeSortKey(self, x): ref = x[0] name = self.getNameKey(ref, x[1]) path = ref.getPath() if ref.flags & eServiceReference.mustDescent and os.path.exists(path): try: mtime = -os.stat(path).st_mtime except (IOError, OSError) as err: mtime = 0 return (0, x[1] and mtime, name) return (1, -x[2], name) def buildDescrAlphaSortKey(self, x): ref = x[0] info = x[1] name = self.getNameKey(ref, info) descr = info and info.getInfoString(ref, iServiceInformation.sDescription) return 1, descr, name, -x[2] def buildGroupwiseSortkey( self, x): # Sort recordings by date, sort MP3 and stuff by name. ref = x[0] return self.buildAlphaNumericSortKey( x ) if ref.type >= eServiceReference.idUser else self.buildBeginTimeSortKey( x) def buildLengthAlphaSortKey(self, x): ref = x[0] info = x[1] name = self.getNameKey(ref, info) len = info and info.getLength(ref) return 1, len, name, -x[2] def buildLengthRevAlphaSortKey(self, x): x = self.buildLengthAlphaSortKey(x) return (x[0], -x[1], x[2], x[3]) def buildSizeAlphaSortKey(self, x): ref = x[0] info = x[1] name = self.getNameKey(ref, info) size = info and info.getFileSize(ref) return 1, size, name, -x[2] def buildSizeRevAlphaSortKey(self, x): x = self.buildSizeAlphaSortKey(x) return (x[0], -x[1], x[2], x[3]) def moveTo(self, serviceref): index = self.findService(serviceref) if index is not None: self.instance.moveSelectionTo(index) return True return False def moveDown(self): self.instance.moveSelection(self.instance.moveDown) def moveUp(self): self.instance.moveSelection(self.instance.moveUp) def moveToChar(self, char, lbl=None): self._char = char self._lbl = lbl if lbl: lbl.setText(self._char) lbl.visible = True self.moveToCharTimer = eTimer() self.moveToCharTimer.callback.append(self._moveToChrStr) self.moveToCharTimer.start( 1000, True ) #time to wait for next key press to decide which letter to use... def moveToString(self, char, lbl=None): self._char = self._char + char.upper() self._lbl = lbl if lbl: lbl.setText(self._char) lbl.visible = True self.moveToCharTimer = eTimer() self.moveToCharTimer.callback.append(self._moveToChrStr) self.moveToCharTimer.start( 1000, True ) #time to wait for next key press to decide which letter to use... def _moveToChrStr(self): currentIndex = self.instance.getCurrentIndex() found = False if currentIndex < (len(self.list) - 1): itemsBelow = self.list[currentIndex + 1:] #first search the items below the selection for index, item in enumerate(itemsBelow): ref = item[0] itemName = getShortName(item[1].getName(ref).upper(), ref) if len(self._char) == 1 and itemName.startswith(self._char): found = True self.instance.moveSelectionTo(index + currentIndex + 1) break elif len(self._char) > 1 and itemName.find(self._char) >= 0: found = True self.instance.moveSelectionTo(index + currentIndex + 1) break if found == False and currentIndex > 0: itemsAbove = self.list[ 1: currentIndex] #first item (0) points parent folder - no point to include for index, item in enumerate(itemsAbove): ref = item[0] itemName = getShortName(item[1].getName(ref).upper(), ref) if len(self._char) == 1 and itemName.startswith(self._char): found = True self.instance.moveSelectionTo(index + 1) break elif len(self._char) > 1 and itemName.find(self._char) >= 0: found = True self.instance.moveSelectionTo(index + 1) break self._char = '' if self._lbl: self._lbl.visible = False
class VirtualKeyBoard(Screen): def __init__(self, session, title="", **kwargs): Screen.__init__(self, session) self.setTitle(_(title)) self.keys_list = [] self.text = "" self.shiftkeys_list = [] self.lang = language.getLanguage() self.nextLang = None self.shiftMode = False self.selectedKey = 0 self.smsChar = None self.sms = NumericalTextInput(self.smsOK) self.key_bg = LoadPixmap(path=resolveFilename( SCOPE_ACTIVE_SKIN, "skin_default/vkey_bg.png")) self.key_sel = LoadPixmap(path=resolveFilename( SCOPE_ACTIVE_SKIN, "skin_default/vkey_sel.png")) self.key_backspace = LoadPixmap(path=resolveFilename( SCOPE_ACTIVE_SKIN, "skin_default/vkey_backspace.png")) self.key_all = LoadPixmap(path=resolveFilename( SCOPE_ACTIVE_SKIN, "skin_default/vkey_all.png")) self.key_clr = LoadPixmap(path=resolveFilename( SCOPE_ACTIVE_SKIN, "skin_default/vkey_clr.png")) self.key_esc = LoadPixmap(path=resolveFilename( SCOPE_ACTIVE_SKIN, "skin_default/vkey_esc.png")) self.key_ok = LoadPixmap(path=resolveFilename( SCOPE_ACTIVE_SKIN, "skin_default/vkey_ok.png")) self.key_shift = LoadPixmap(path=resolveFilename( SCOPE_ACTIVE_SKIN, "skin_default/vkey_shift.png")) self.key_shift_sel = LoadPixmap(path=resolveFilename( SCOPE_ACTIVE_SKIN, "skin_default/vkey_shift_sel.png")) self.key_space = LoadPixmap(path=resolveFilename( SCOPE_ACTIVE_SKIN, "skin_default/vkey_space.png")) self.key_left = LoadPixmap(path=resolveFilename( SCOPE_ACTIVE_SKIN, "skin_default/vkey_left.png")) self.key_right = LoadPixmap(path=resolveFilename( SCOPE_ACTIVE_SKIN, "skin_default/vkey_right.png")) self.keyImages = { "BACKSPACE": self.key_backspace, "ALL": self.key_all, "EXIT": self.key_esc, "OK": self.key_ok, "SHIFT": self.key_shift, "SPACE": self.key_space, "LEFT": self.key_left, "RIGHT": self.key_right } self.keyImagesShift = { "BACKSPACE": self.key_backspace, "CLEAR": self.key_clr, "EXIT": self.key_esc, "OK": self.key_ok, "SHIFT": self.key_shift_sel, "SPACE": self.key_space, "LEFT": self.key_left, "RIGHT": self.key_right } self["country"] = Label(_("Keyboard language")) self["header"] = Label(title) self["text"] = Input(currPos=len( kwargs.get("text", "").decode("utf-8", 'ignore')), allMarked=False, **kwargs) self["list"] = VirtualKeyBoardList([]) self["actions"] = NumberActionMap( [ "OkCancelActions", "WizardActions", "ColorActions", "KeyboardInputActions", "InputBoxActions", "InputAsciiActions" ], { "gotAsciiCode": self.keyGotAscii, "ok": self.okClicked, "cancel": self.exit, "left": self.left, "right": self.right, "up": self.up, "down": self.down, "red": self.exit, "green": self.ok, "yellow": self.switchLang, "blue": self.shiftClicked, "deleteBackward": self.backClicked, "deleteForward": self.forwardClicked, "back": self.exit, "pageUp": self.cursorRight, "pageDown": self.cursorLeft, "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, }, -2) self.setLang() self.onExecBegin.append(self.setKeyboardModeAscii) self.onLayoutFinish.append(self.buildVirtualKeyBoard) def switchLang(self): self.lang = self.nextLang self.setLang() self.buildVirtualKeyBoard() def setLang(self): if self.lang == 'de_DE': self.keys_list = [[ u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE" ], [ u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"ü", u"+" ], [ u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ö", u"ä", u"#" ], [ u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL" ], [ u"SHIFT", u"SPACE", u"@", u"ß", u"OK", u"LEFT", u"RIGHT" ]] self.shiftkeys_list = [[ u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE" ], [ u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"Ü", u"*" ], [ u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"Ö", u"Ä", u"'" ], [ u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR" ], [ u"SHIFT", u"SPACE", u"?", u"\\", u"OK", u"LEFT", u"RIGHT" ]] self.nextLang = 'th_TH' elif self.lang == 'th_TH': self.keys_list = [ [ u'EXIT', '\xe0\xb9\x85', '\xe0\xb8\xa0', '\xe0\xb8\x96', '\xe0\xb8\xb8', '\xe0\xb8\xb6', '\xe0\xb8\x84', '\xe0\xb8\x95', '\xe0\xb8\x88', '\xe0\xb8\x82', '\xe0\xb8\x8a', u'BACKSPACE' ], [ '\xe0\xb9\x86', '\xe0\xb9\x84', '\xe0\xb8\xb3', '\xe0\xb8\x9e', '\xe0\xb8\xb0', '\xe0\xb8\xb1', '\xe0\xb8\xb5', '\xe0\xb8\xa3', '\xe0\xb8\x99', '\xe0\xb8\xa2', '\xe0\xb8\x9a', '\xe0\xb8\xa5' ], [ '\xe0\xb8\x9f', '\xe0\xb8\xab', '\xe0\xb8\x81', '\xe0\xb8\x94', '\xe0\xb9\x80', '\xe0\xb9\x89', '\xe0\xb9\x88', '\xe0\xb8\xb2', '\xe0\xb8\xaa', '\xe0\xb8\xa7', '\xe0\xb8\x87' ], [ '\xe0\xb8\x9c', '\xe0\xb8\x9b', '\xe0\xb9\x81', '\xe0\xb8\xad', '\xe0\xb8\xb4', '\xe0\xb8\xb7', '\xe0\xb8\x97', '\xe0\xb8\xa1', '\xe0\xb9\x83', '\xe0\xb8\x9d' ], [u'SHIFT', u'SPACE', u'OK'] ] self.shiftkeys_list = [[ 'EXIT', '\xe0\xb9\x91', '\xe0\xb9\x92', '\xe0\xb9\x93', '\xe0\xb9\x94', '\xe0\xb8\xb9', '\xe0\xb8\xbf', '\xe0\xb9\x95', '\xe0\xb9\x96', '\xe0\xb9\x97', '\xe0\xb9\x98', '\xe0\xb9\x99', u'BACKSPACE' ], [ '\xe0\xb9\x90', '', '\xe0\xb8\x8e', '\xe0\xb8\x91', '\xe0\xb8\x98', '\xe0\xb9\x8d', '\xe0\xb9\x8a', '\xe0\xb8\x93', '\xe0\xb8\xaf', '\xe0\xb8\x8d', '\xe0\xb8\x90' ], [ '\xe0\xb8\xa4', '\xe0\xb8\x86', '\xe0\xb8\x8f', '\xe0\xb9\x82', '\xe0\xb8\x8c', '\xe0\xb9\x87', '\xe0\xb9\x8b', '\xe0\xb8\xa9', '\xe0\xb8\xa8', '\xe0\xb8\x8b' ], [ '', '', '\xe0\xb8\x89', '\xe0\xb8\xae', '\xe0\xb8\xba', '\xe0\xb9\x8c', '', '\xe0\xb8\x92', '\xe0\xb8\xac', '\xe0\xb8\xa6', u'CLEAR' ], [u'SHIFT', u'SPACE', u'OK']] self.nextLang = 'en_EN' elif self.lang == 'es_ES': #still missing keys (u"ùÙ") self.keys_list = [[ u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE" ], [ u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"ú", u"+" ], [ u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ó", u"á", u"#" ], [ u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL" ], [ u"SHIFT", u"SPACE", u"@", u"Ł", u"ŕ", u"é", u"č", u"í", u"ě", u"ń", u"ň", u"OK" ]] self.shiftkeys_list = [[ u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE" ], [ u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"Ú", u"*" ], [ u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"Ó", u"Á", u"'" ], [ u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR" ], [ u"SHIFT", u"SPACE", u"?", u"\\", u"Ŕ", u"É", u"Č", u"Í", u"Ě", u"Ń", u"Ň", u"OK" ]] self.nextLang = 'en_EN' elif self.lang == 'fi_FI': self.keys_list = [[ u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE" ], [ u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"é", u"+" ], [ u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ö", u"ä", u"#" ], [ u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL" ], [ u"SHIFT", u"SPACE", u"@", u"ß", u"ĺ", u"OK", u"LEFT", u"RIGHT" ]] self.shiftkeys_list = [[ u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE" ], [ u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"É", u"*" ], [ u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"Ö", u"Ä", u"'" ], [ u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR" ], [ u"SHIFT", u"SPACE", u"?", u"\\", u"Ĺ", u"OK", u"LEFT", u"RIGHT" ]] self.nextLang = 'en_EN' elif self.lang == 'ru_RU': self.keys_list = [[ u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE" ], [ u"а", u"б", u"в", u"г", u"д", u"е", u"ё", u"ж", u"з", u"и", u"й", u"+" ], [ u"к", u"л", u"м", u"н", u"о", u"п", u"р", u"с", u"т", u"у", u"ф", u"#" ], [ u"<", u"х", u"ц", u"ч", u"ш", u"щ", u"ъ", u"ы", u",", u".", u"-", u"ALL" ], [ u"SHIFT", u"SPACE", u"@", u"ь", u"э", u"ю", u"я", u"OK", u"LEFT", u"RIGHT" ]] self.shiftkeys_list = [[ u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE" ], [ u"А", u"Б", u"В", u"Г", u"Д", u"Е", u"Ё", u"Ж", u"З", u"И", u"Й", u"*" ], [ u"К", u"Л", u"М", u"Н", u"О", u"П", u"Р", u"С", u"Т", u"У", u"Ф", u"'" ], [ u">", u"Х", u"Ц", u"Ч", u"Ш", u"Щ", u"Ъ", u"Ы", u";", u":", u"_", u"CLEAR" ], [ u"SHIFT", u"SPACE", u"?", u"\\", u"Ь", u"Э", u"Ю", u"Я", u"OK", u"LEFT", u"RIGHT" ]] self.nextLang = 'en_EN' elif self.lang == 'sv_SE': self.keys_list = [[ u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE" ], [ u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"é", u"+" ], [ u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ö", u"ä", u"#" ], [ u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL" ], [ u"SHIFT", u"SPACE", u"@", u"ß", u"ĺ", u"OK", u"LEFT", u"RIGHT" ]] self.shiftkeys_list = [[ u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE" ], [ u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"É", u"*" ], [ u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"Ö", u"Ä", u"'" ], [ u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR" ], [ u"SHIFT", u"SPACE", u"?", u"\\", u"Ĺ", u"OK", u"LEFT", u"RIGHT" ]] self.nextLang = 'en_EN' elif self.lang == 'sk_SK': self.keys_list = [[ u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE" ], [ u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"ú", u"+" ], [ u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ľ", u"@", u"#" ], [ u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL" ], [ u"SHIFT", u"SPACE", u"š", u"č", u"ž", u"ý", u"á", u"í", u"é", u"OK", u"LEFT", u"RIGHT" ]] self.shiftkeys_list = [[ u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE" ], [ u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"ť", u"*" ], [ u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"ň", u"ď", u"'" ], [ u"Á", u"É", u"Ď", u"Í", u"Ý", u"Ó", u"Ú", u"Ž", u"Š", u"Č", u"Ť", u"Ň" ], [ u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR" ], [ u"SHIFT", u"SPACE", u"?", u"\\", u"ä", u"ö", u"ü", u"ô", u"ŕ", u"ĺ", u"OK" ]] self.nextLang = 'en_EN' elif self.lang == 'cs_CZ': self.keys_list = [[ u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE" ], [ u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"ú", u"+" ], [ u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ů", u"@", u"#" ], [ u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL" ], [ u"SHIFT", u"SPACE", u"ě", u"š", u"č", u"ř", u"ž", u"ý", u"á", u"í", u"é", u"OK" ]] self.shiftkeys_list = [[ u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE" ], [ u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"ť", u"*" ], [ u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"ň", u"ď", u"'" ], [ u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR" ], [ u"SHIFT", u"SPACE", u"?", u"\\", u"Č", u"Ř", u"Š", u"Ž", u"Ú", u"Á", u"É", u"OK" ]] self.nextLang = 'el_GR' elif self.lang == 'el_GR': self.keys_list = [[ u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE" ], [ u"=", u"ς", u"ε", u"ρ", u"τ", u"υ", u"θ", u"ι", u"ο", u"π", u"[", u"]" ], [ u"α", u"σ", u"δ", u"φ", u"γ", u"η", u"ξ", u"κ", u"λ", u";", u"'", u"-" ], [ u"\\", u"ζ", u"χ", u"ψ", u"ω", u"β", u"ν", u"μ", u",", ".", u"/", u"ALL" ], [ u"SHIFT", u"SPACE", u"ά", u"έ", u"ή", u"ί", u"ό", u"ύ", u"ώ", u"ϊ", u"ϋ", u"OK" ]] self.shiftkeys_list = [[ u"EXIT", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"*", u"(", u")", u"BACKSPACE" ], [ u"+", u"€", u"Ε", u"Ρ", u"Τ", u"Υ", u"Θ", u"Ι", u"Ο", u"Π", u"{", u"}" ], [ u"Α", u"Σ", u"Δ", u"Φ", u"Γ", u"Η", u"Ξ", u"Κ", u"Λ", u":", u'"', u"_" ], [ u"|", u"Ζ", u"Χ", u"Ψ", u"Ω", u"Β", u"Ν", u"Μ", u"<", u">", u"?", u"CLEAR" ], [ u"SHIFT", u"SPACE", u"Ά", u"Έ", u"Ή", u"Ί", u"Ό", u"Ύ", u"Ώ", u"Ϊ", u"Ϋ", u"OK" ]] self.nextLang = 'pl_PL' elif self.lang == 'pl_PL': self.keys_list = [[ u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE" ], [ u"q", u"w", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"-", u"[" ], [ u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u";", u"'", u"\\" ], [ u"<", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"/", u"ALL" ], [ u"SHIFT", u"SPACE", u"ą", u"ć", u"ę", u"ł", u"ń", u"ó", u"ś", u"ź", u"ż", u"OK" ]] self.shiftkeys_list = [[ u"EXIT", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"(", u")", u"=", u"BACKSPACE" ], [ u"Q", u"W", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"*", u"]" ], [ u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"?", u'"', u"|" ], [ u">", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR" ], [ u"SHIFT", u"SPACE", u"Ą", u"Ć", u"Ę", u"Ł", u"Ń", u"Ó", u"Ś", u"Ź", u"Ż", u"OK" ]] self.nextLang = 'en_EN' elif self.lang == 'pl_PL': self.keys_list = [[ u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE" ], [ u"q", u"w", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"-", u"[" ], [ u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u";", u"'", u"\\" ], [ u"<", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"/", u"CLEAR" ], [ u"SHIFT", u"SPACE", u"ą", u"ć", u"ę", u"ł", u"ń", u"ó", u"ś", u"ź", u"ż", u"OK" ]] self.shiftkeys_list = [[ u"EXIT", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"(", u")", u"=", u"BACKSPACE" ], [ u"Q", u"W", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"*", u"]" ], [ u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"?", u'"', u"|" ], [ u">", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR" ], [ u"SHIFT", u"SPACE", u"Ą", u"Ć", u"Ę", u"Ł", u"Ń", u"Ó", u"Ś", u"Ź", u"Ż", u"OK" ]] self.nextLang = 'en_EN' elif self.lang == 'tr_TR': self.keys_list = [[ u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE" ], [ u"f", u"g", u"ğ", u"i", u"o", u"d", u"r", u"n", u"h", u"p", u"q", u"w" ], [ u"u", u"i", u"e", u"a", u"ü", u"t", u"k", u"m", u"l", u"y", u"ş", u"-" ], [ u"j", u"ö", u"v", u"c", u"ç", u"z", u"s", u"b", u"x", u",", ".", u"CLEAR" ], [u"SHIFT", u"SPACE", u"+", u"OK"]] self.shiftkeys_list = [[ u"EXIT", u"*", u'"', u"^", u"$", u"%", u"'", u"(", u")", u"=", u"?", u"BACKSPACE" ], [ u"F", u"G", u"Ğ", u"I", u"O", u"D", u"R", u"N", u"H", u"P", u"Q", u"W" ], [ u"U", u"İ", u"E", u"A", u"Ü", u"T", u"K", u"M", u"L", u"Ş", u"|", u"X" ], [ u"J", u"Ö", u"V", u"C", u"Ç", u"Z", u"S", u"B", u"_", u"CLEAR" ], [ u"SHIFT", u"SPACE", u",", u";", u":", u"OK" ]] self.nextLang = 'en_EN' else: self.keys_list = [[ u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE" ], [ u"q", u"w", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"-", u"[" ], [ u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u";", u"'", u"\\" ], [ u"<", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"/", u"ALL" ], [u"SHIFT", u"SPACE", u"OK", u"LEFT", u"RIGHT"]] self.shiftkeys_list = [[ u"EXIT", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"(", u")", u"=", u"BACKSPACE" ], [ u"Q", u"W", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"*", u"]" ], [ u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"?", u'"', u"|" ], [ u">", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR" ], [ u"SHIFT", u"SPACE", u"OK", u"LEFT", u"RIGHT" ]] self.lang = 'en_EN' self.nextLang = language.getLanguage() self["country"].setText( self.lang + (_(" press Yellow to change Keyboard language"))) self.max_key = 47 + len(self.keys_list[4]) def virtualKeyBoardEntryComponent(self, keys): key_bg_width = self.key_bg and self.key_bg.size().width() or 45 key_images = self.shiftMode and self.keyImagesShift or self.keyImages res = [keys] text = [] x = 0 for key in keys: png = key_images.get(key, None) if png: width = png.size().width() res.append( MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=png)) else: width = key_bg_width res.append( MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=self.key_bg)) text.append( MultiContentEntryText(pos=(x, 0), size=(width, 45), font=0, text=key.encode("utf-8"), flags=RT_HALIGN_CENTER | RT_VALIGN_CENTER)) x += width return res + text def buildVirtualKeyBoard(self): self.previousSelectedKey = None self.list = [] for keys in self.shiftMode and self.shiftkeys_list or self.keys_list: self.list.append(self.virtualKeyBoardEntryComponent(keys)) self.markSelectedKey() def markSelectedKey(self): if self.previousSelectedKey is not None: self.list[self.previousSelectedKey / 12] = self.list[self.previousSelectedKey / 12][:-1] width = self.key_sel.size().width() x = self.list[self.selectedKey / 12][self.selectedKey % 12 + 1][1] self.list[self.selectedKey / 12].append( MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, 45), png=self.key_sel)) self.previousSelectedKey = self.selectedKey self["list"].setList(self.list) def backClicked(self): self["text"].deleteBackward() def forwardClicked(self): self["text"].deleteForward() def shiftClicked(self): self.smsChar = None self.shiftMode = not self.shiftMode self.buildVirtualKeyBoard() def okClicked(self): self.smsChar = None text = (self.shiftMode and self.shiftkeys_list or self.keys_list)[self.selectedKey / 12][self.selectedKey % 12].encode("UTF-8") if text == "EXIT": self.close(None) elif text == "BACKSPACE": self["text"].deleteBackward() elif text == "ALL": self["text"].markAll() elif text == "CLEAR": self["text"].deleteAllChars() self["text"].update() elif text == "SHIFT": self.shiftClicked() elif text == "SPACE": self["text"].char(" ".encode("UTF-8")) elif text == "OK": self.close(self["text"].getText().encode("UTF-8")) elif text == "LEFT": self["text"].left() elif text == "RIGHT": self["text"].right() else: self["text"].char(text) def ok(self): self.close(self["text"].getText().encode("UTF-8")) def exit(self): self.close(None) def cursorRight(self): self["text"].right() def cursorLeft(self): self["text"].left() def left(self): self.smsChar = None self.selectedKey = self.selectedKey / 12 * 12 + (self.selectedKey + 11) % 12 if self.selectedKey > self.max_key: self.selectedKey = self.max_key self.markSelectedKey() def right(self): self.smsChar = None self.selectedKey = self.selectedKey / 12 * 12 + (self.selectedKey + 1) % 12 if self.selectedKey > self.max_key: self.selectedKey = self.selectedKey / 12 * 12 self.markSelectedKey() def up(self): self.smsChar = None self.selectedKey -= 12 if self.selectedKey < 0: self.selectedKey = self.max_key / 12 * 12 + self.selectedKey % 12 if self.selectedKey > self.max_key: self.selectedKey -= 12 self.markSelectedKey() def down(self): self.smsChar = None self.selectedKey += 12 if self.selectedKey > self.max_key: self.selectedKey %= 12 self.markSelectedKey() def keyNumberGlobal(self, number): if number == 1: self.text += "1" self["text"].setText(self.text.encode("utf-8")) elif number == 2: self.text += "2" self["text"].setText(self.text.encode("utf-8")) elif number == 3: self.text += "3" self["text"].setText(self.text.encode("utf-8")) elif number == 4: self.text += "4" self["text"].setText(self.text.encode("utf-8")) elif number == 5: self.text += "5" self["text"].setText(self.text.encode("utf-8")) elif number == 6: self.text += "6" self["text"].setText(self.text.encode("utf-8")) elif number == 7: self.text += "7" self["text"].setText(self.text.encode("utf-8")) elif number == 8: self.text += "8" self["text"].setText(self.text.encode("utf-8")) elif number == 9: self.text += "9" self["text"].setText(self.text.encode("utf-8")) elif number == 0: self.text += "0" self["text"].setText(self.text.encode("utf-8")) else: self.smsChar = self.sms.getKey(number) print "SMS", number, self.smsChar self.selectAsciiKey(self.smsChar) def smsOK(self): if self.smsChar and self.selectAsciiKey(self.smsChar): print "pressing ok now" self.okClicked() def keyGotAscii(self): #self.smsChar = None #if self.selectAsciiKey(str(unichr(getPrevAsciiCode()).encode('utf-8'))): #self.okClicked() pass def selectAsciiKey(self, char): if char == " ": char = "SPACE" for keyslist in (self.shiftkeys_list, self.keys_list): selkey = 0 for keys in keyslist: for key in keys: if key == char: self.selectedKey = selkey if self.shiftMode != (keyslist is self.shiftkeys_list): self.shiftMode = not self.shiftMode self.buildVirtualKeyBoard() else: self.markSelectedKey() return True selkey += 1 return False
class MovieList(GUIComponent): SORT_ALPHANUMERIC = 1 SORT_RECORDED = 2 SHUFFLE = 3 SORT_ALPHANUMERIC_REVERSE = 4 SORT_RECORDED_REVERSE = 5 SORT_ALPHANUMERIC_FLAT = 6 SORT_ALPHANUMERIC_FLAT_REVERSE = 7 SORT_GROUPWISE = 8 SORT_ALPHA_DATE_OLDEST_FIRST = 9 SORT_ALPHAREV_DATE_NEWEST_FIRST = 10 HIDE_DESCRIPTION = 1 SHOW_DESCRIPTION = 2 def __init__(self, root, sort_type = None, descr_state = None): GUIComponent.__init__(self) self.list = [] self.descr_state = descr_state or self.HIDE_DESCRIPTION self.sort_type = sort_type or self.SORT_GROUPWISE self.firstFileEntry = 0 self.parentDirectory = 0 self.fontName = 'Regular' self.fontSize = 20 self.listHeight = None self.listWidth = None self.pbarShift = 5 self.pbarHeight = 16 self.pbarLargeWidth = 48 self.pbarColour = 2122547 self.pbarColourSeen = 16762653 self.pbarColourRec = 16711709 self.partIconeShift = 5 self.spaceRight = 2 self.spaceIconeText = 2 self.iconsWidth = 22 self.trashShift = 1 self.dirShift = 1 self.dateWidth = 150 self.reloadDelayTimer = None self.l = eListboxPythonMultiContent() self.tags = set() self.root = None self.list = None self._playInBackground = None self._playInForeground = None self._char = '' if root is not None: self.reload(root) self.l.setBuildFunc(self.buildMovieListEntry) self.onSelectionChanged = [] self.iconPart = [] for part in range(5): self.iconPart.append(LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/part_%d_4.png' % part))) self.iconMovieRec = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/part_new.png')) self.iconMoviePlay = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/movie_play.png')) self.iconMoviePlayRec = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/movie_play_rec.png')) self.iconUnwatched = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/part_unwatched.png')) self.iconFolder = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/folder.png')) self.iconTrash = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/trashcan.png')) self.runningTimers = {} self.updateRecordings() self.updatePlayPosCache() return def get_playInBackground(self): return self._playInBackground def set_playInBackground(self, value): if self._playInBackground is not value: index = self.findService(self._playInBackground) if index is not None: self.invalidateItem(index) self.l.invalidateEntry(index) index = self.findService(value) if index is not None: self.invalidateItem(index) self.l.invalidateEntry(index) self._playInBackground = value return playInBackground = property(get_playInBackground, set_playInBackground) def get_playInForeground(self): return self._playInForeground def set_playInForeground(self, value): self._playInForeground = value playInForeground = property(get_playInForeground, set_playInForeground) def updatePlayPosCache(self): from Screens.InfoBarGenerics import updateresumePointCache updateresumePointCache() def updateRecordings(self, timer = None): if timer is not None: if timer.justplay: return result = {} for timer in NavigationInstance.instance.RecordTimer.timer_list: if timer.isRunning() and not timer.justplay: result[os.path.split(timer.Filename)[1] + '.ts'] = timer if self.runningTimers == result: return else: self.runningTimers = result if timer is not None: if self.reloadDelayTimer is not None: self.reloadDelayTimer.stop() self.reloadDelayTimer = eTimer() self.reloadDelayTimer.callback.append(self.reload) self.reloadDelayTimer.start(5000, 1) return def connectSelChanged(self, fnc): if fnc not in self.onSelectionChanged: self.onSelectionChanged.append(fnc) def disconnectSelChanged(self, fnc): if fnc in self.onSelectionChanged: self.onSelectionChanged.remove(fnc) def selectionChanged(self): for x in self.onSelectionChanged: x() def setDescriptionState(self, val): self.descr_state = val def setSortType(self, type): self.sort_type = type def applySkin(self, desktop, parent): def warningWrongSkinParameter(string): print "[MovieList] wrong '%s' skin parameters" % string def font(value): font = skin.parseFont(value, ((1, 1), (1, 1))) self.fontName = font.family self.fontSize = font.pointSize def pbarShift(value): self.pbarShift = int(value) def pbarHeight(value): self.pbarHeight = int(value) def pbarLargeWidth(value): self.pbarLargeWidth = int(value) def pbarColour(value): self.pbarColour = skin.parseColor(value).argb() def pbarColourSeen(value): self.pbarColourSeen = skin.parseColor(value).argb() def pbarColourRec(value): self.pbarColourRec = skin.parseColor(value).argb() def partIconeShift(value): self.partIconeShift = int(value) def spaceIconeText(value): self.spaceIconeText = int(value) def iconsWidth(value): self.iconsWidth = int(value) def trashShift(value): self.trashShift = int(value) def dirShift(value): self.dirShift = int(value) def spaceRight(value): self.spaceRight = int(value) def dateWidth(value): self.dateWidth = int(value) for attrib, value in self.skinAttributes[:]: try: locals().get(attrib)(value) self.skinAttributes.remove((attrib, value)) except: pass rc = GUIComponent.applySkin(self, desktop, parent) self.listHeight = self.instance.size().height() self.listWidth = self.instance.size().width() self.setFontsize() self.setItemsPerPage() return rc def setItemsPerPage(self): if self.listHeight > 0: itemHeight = self.listHeight / config.movielist.itemsperpage.value else: itemHeight = 30 self.itemHeight = itemHeight self.l.setItemHeight(itemHeight) self.instance.resize(eSize(self.listWidth, self.listHeight / itemHeight * itemHeight)) def setFontsize(self): self.l.setFont(0, gFont(self.fontName, self.fontSize + config.movielist.fontsize.value)) self.l.setFont(1, gFont(self.fontName, self.fontSize - 3 + config.movielist.fontsize.value)) def invalidateItem(self, index): x = self.list[index] self.list[index] = (x[0], x[1], x[2], None) return def invalidateCurrentItem(self): self.invalidateItem(self.getCurrentIndex()) def buildMovieListEntry(self, serviceref, info, begin, data): switch = config.usage.show_icons_in_movielist.value width = self.l.getItemSize().width() dateWidth = self.dateWidth iconSize = self.iconsWidth space = self.spaceIconeText r = self.spaceRight pathName = serviceref.getPath() res = [None] if serviceref.flags & eServiceReference.mustDescent: if info is None: txt = '..' else: p = os.path.split(pathName) if not p[1]: p = os.path.split(p[0]) txt = p[1] if txt == '.Trash': res.append(MultiContentEntryPixmapAlphaBlend(pos=(0, self.trashShift), size=(iconSize, self.iconTrash.size().height()), png=self.iconTrash)) res.append(MultiContentEntryText(pos=(iconSize + space, 0), size=(width - 166, self.itemHeight), font=0, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER, text=_('Deleted items'))) res.append(MultiContentEntryText(pos=(width - 145 - r, 0), size=(145, self.itemHeight), font=1, flags=RT_HALIGN_RIGHT | RT_VALIGN_CENTER, text=_('Trash can'))) return res res.append(MultiContentEntryPixmapAlphaBlend(pos=(0, self.dirShift), size=(iconSize, iconSize), png=self.iconFolder)) res.append(MultiContentEntryText(pos=(iconSize + space, 0), size=(width - 166, self.itemHeight), font=0, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER, text=txt)) res.append(MultiContentEntryText(pos=(width - 145 - r, 0), size=(145, self.itemHeight), font=1, flags=RT_HALIGN_RIGHT | RT_VALIGN_CENTER, text=_('Directory'))) return res else: if data == -1 or data is None: data = MovieListData() cur_idx = self.l.getCurrentSelectionIndex() x = self.list[cur_idx] data.len = 0 self.list[cur_idx] = (x[0], x[1], x[2], data) data.txt = info.getName(serviceref) if config.movielist.hide_extensions.value: fileName, fileExtension = os.path.splitext(data.txt) if fileExtension in KNOWN_EXTENSIONS: data.txt = fileName data.icon = None data.part = None if os.path.split(pathName)[1] in self.runningTimers: if switch == 'i': if (self.playInBackground or self.playInForeground) and serviceref == (self.playInBackground or self.playInForeground): data.icon = self.iconMoviePlayRec else: data.icon = self.iconMovieRec elif switch in ('p', 's'): data.part = 100 if (self.playInBackground or self.playInForeground) and serviceref == (self.playInBackground or self.playInForeground): data.partcol = self.pbarColourSeen else: data.partcol = self.pbarColourRec elif (self.playInBackground or self.playInForeground) and serviceref == (self.playInBackground or self.playInForeground): data.icon = self.iconMoviePlay else: data.part = moviePlayState(pathName + '.cuts', serviceref, data.len) if switch == 'i': if data.part is not None and data.part > 0: data.icon = self.iconPart[data.part // 25] elif config.usage.movielist_unseen.value: data.icon = self.iconUnwatched elif switch in ('p', 's'): if data.part is not None and data.part > 0: data.partcol = self.pbarColourSeen elif config.usage.movielist_unseen.value: data.part = 100 data.partcol = self.pbarColour len = data.len if len > 0: len = '%d:%02d' % (len / 60, len % 60) else: len = '' if data: pos = (0, self.partIconeShift) if switch == 'i' and hasattr(data, 'icon') and data.icon is not None: res.append(MultiContentEntryPixmapAlphaBlend(pos=pos, size=(iconSize, data.icon.size().height()), png=data.icon)) elif switch in ('p', 's'): if switch == 'p': iconSize = self.pbarLargeWidth if hasattr(data, 'part') and data.part > 0: res.append(MultiContentEntryProgress(pos=(0, self.pbarShift), size=(iconSize, self.pbarHeight), percent=data.part, borderWidth=2, foreColor=data.partcol, foreColorSelected=None, backColor=None, backColorSelected=None)) elif hasattr(data, 'icon') and data.icon is not None: res.append(MultiContentEntryPixmapAlphaBlend(pos=(0, self.pbarShift), size=(iconSize, self.pbarHeight), png=data.icon)) begin_string = '' if begin > 0: begin_string = ' '.join(FuzzyTime(begin, inPast=True)) ih = self.itemHeight res.append(MultiContentEntryText(pos=(iconSize + space, 0), size=(width - iconSize - space - dateWidth - r, ih), font=0, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER, text=data.txt)) res.append(MultiContentEntryText(pos=(width - dateWidth - r, 0), size=(dateWidth, ih), font=1, flags=RT_HALIGN_RIGHT | RT_VALIGN_CENTER, text=begin_string)) return res def moveToFirstMovie(self): if self.firstFileEntry < len(self.list): self.instance.moveSelectionTo(self.firstFileEntry) else: self.moveToFirst() def moveToParentDirectory(self): if self.parentDirectory < len(self.list): self.instance.moveSelectionTo(self.parentDirectory) else: self.moveToFirst() def moveToLast(self): if self.list: self.instance.moveSelectionTo(len(self.list) - 1) def moveToFirst(self): if self.list: self.instance.moveSelectionTo(0) def moveToIndex(self, index): self.instance.moveSelectionTo(index) def getCurrentIndex(self): return self.instance.getCurrentIndex() def getCurrentEvent(self): l = self.l.getCurrentSelection() return l and l[0] and l[1] and l[1].getEvent(l[0]) def getCurrent(self): l = self.l.getCurrentSelection() return l and l[0] def getItem(self, index): if self.list: if len(self.list) > index: return self.list[index] and self.list[index][0] GUI_WIDGET = eListbox def postWidgetCreate(self, instance): instance.setContent(self.l) instance.selectionChanged.get().append(self.selectionChanged) self.setFontsize() def preWidgetRemove(self, instance): instance.setContent(None) instance.selectionChanged.get().remove(self.selectionChanged) return def reload(self, root = None, filter_tags = None): if self.reloadDelayTimer is not None: self.reloadDelayTimer.stop() self.reloadDelayTimer = None if root is not None: self.load(root, filter_tags) else: self.load(self.root, filter_tags) self.l.setList(self.list) return def removeService(self, service): index = self.findService(service) if index is not None: del self.list[index] self.l.setList(self.list) return def findService(self, service): if service is None: return else: for index, l in enumerate(self.list): if l[0] == service: return index return def __len__(self): return len(self.list) def __getitem__(self, index): return self.list[index] def __iter__(self): return self.list.__iter__() def load(self, root, filter_tags): self.list = [] serviceHandler = eServiceCenter.getInstance() numberOfDirs = 0 reflist = serviceHandler.list(root) if reflist is None: print 'listing of movies failed' return else: realtags = set() autotags = {} rootPath = os.path.normpath(root.getPath()) parent = None if len(rootPath) > 1 and os.path.realpath(rootPath) != os.path.realpath(config.movielist.root.value): parent = os.path.split(os.path.normpath(rootPath))[0] currentfolder = os.path.normpath(rootPath) + '/' if parent and parent not in defaultInhibitDirs and not currentfolder.endswith(config.usage.default_path.value): if not parent.endswith('/'): parent += '/' ref = eServiceReference('2:0:1:0:0:0:0:0:0:0:' + parent) ref.flags = eServiceReference.flagDirectory self.list.append((ref, None, 0, -1)) numberOfDirs += 1 while 1: serviceref = reflist.getNext() if not serviceref.valid(): break if config.ParentalControl.servicepinactive.value and config.ParentalControl.storeservicepin.value != 'never': from Components.ParentalControl import parentalControl if not parentalControl.sessionPinCached and parentalControl.isProtected(serviceref): continue info = serviceHandler.info(serviceref) if info is None: info = justStubInfo begin = info.getInfo(serviceref, iServiceInformation.sTimeCreate) if serviceref.flags & eServiceReference.mustDescent: dirname = info.getName(serviceref) if not dirname.endswith('.AppleDouble/') and not dirname.endswith('.AppleDesktop/') and not dirname.endswith('.AppleDB/') and not dirname.endswith('Network Trash Folder/') and not dirname.endswith('Temporary Items/'): self.list.append((serviceref, info, begin, -1)) numberOfDirs += 1 continue this_tags = info.getInfoString(serviceref, iServiceInformation.sTags).split(' ') name = info.getName(serviceref) if name[:2] == '._': continue if this_tags == ['']: this_tags = name.replace(',', ' ').replace('.', ' ').replace('_', ' ').replace(':', ' ').split() for tag in this_tags: if autotags.has_key(tag): autotags[tag].append(name) else: autotags[tag] = [name] else: realtags.update(this_tags) if filter_tags is not None: this_tags_fullname = [' '.join(this_tags)] this_tags_fullname = set(this_tags_fullname) this_tags = set(this_tags) if not this_tags.issuperset(filter_tags) and not this_tags_fullname.issuperset(filter_tags): continue self.list.append((serviceref, info, begin, -1)) self.firstFileEntry = numberOfDirs self.parentDirectory = 0 self.list.sort(key=self.buildGroupwiseSortkey) if self.sort_type == MovieList.SORT_ALPHANUMERIC: self.list = sorted(self.list[:numberOfDirs], key=self.buildAlphaNumericSortKey) + sorted(self.list[numberOfDirs:], key=self.buildAlphaNumericSortKey) elif self.sort_type == MovieList.SORT_ALPHANUMERIC_REVERSE: self.list = sorted(self.list[:numberOfDirs], key=self.buildAlphaNumericSortKey, reverse=True) + sorted(self.list[numberOfDirs:], key=self.buildAlphaNumericSortKey, reverse=True) elif self.sort_type == MovieList.SORT_ALPHANUMERIC_FLAT: self.list.sort(key=self.buildAlphaNumericFlatSortKey) elif self.sort_type == MovieList.SORT_ALPHANUMERIC_FLAT_REVERSE: self.list.sort(key=self.buildAlphaNumericFlatSortKey, reverse=True) elif self.sort_type == MovieList.SORT_RECORDED: self.list = sorted(self.list[:numberOfDirs], key=self.buildAlphaNumericSortKey) + sorted(self.list[numberOfDirs:], key=self.buildBeginTimeSortKey) elif self.sort_type == MovieList.SORT_RECORDED_REVERSE: self.list = sorted(self.list[:numberOfDirs], key=self.buildAlphaNumericSortKey, reverse=True) + sorted(self.list[numberOfDirs:], key=self.buildBeginTimeSortKey, reverse=True) elif self.sort_type == MovieList.SHUFFLE: dirlist = self.list[:numberOfDirs] shufflelist = self.list[numberOfDirs:] random.shuffle(shufflelist) self.list = dirlist + shufflelist elif self.sort_type == MovieList.SORT_ALPHA_DATE_OLDEST_FIRST: self.list = sorted(self.list[:numberOfDirs], key=self.buildAlphaDateSortKey) + sorted(self.list[numberOfDirs:], key=self.buildAlphaDateSortKey) elif self.sort_type == MovieList.SORT_ALPHAREV_DATE_NEWEST_FIRST: self.list = sorted(self.list[:numberOfDirs], key=self.buildAlphaDateSortKey, reverse=True) + sorted(self.list[numberOfDirs:], key=self.buildAlphaDateSortKey, reverse=True) for x in self.list: if x[1]: tmppath = x[1].getName(x[0])[:-1] if x[1].getName(x[0]).endswith('/') else x[1].getName(x[0]) if tmppath.endswith('.Trash'): self.list.insert(0, self.list.pop(self.list.index(x))) break if self.root and numberOfDirs > 0: rootPath = os.path.normpath(self.root.getPath()) if not rootPath.endswith('/'): rootPath += '/' if rootPath != parent: for index, item in enumerate(self.list): if item[0].flags & eServiceReference.mustDescent: itempath = os.path.normpath(item[0].getPath()) if not itempath.endswith('/'): itempath += '/' if itempath == rootPath: self.parentDirectory = index break self.root = root rautotags = {} for tag, movies in autotags.items(): if len(movies) > 1: movies = tuple(movies) item = rautotags.get(movies, []) if not item: rautotags[movies] = item item.append(tag) self.tags = {} for movies, tags in rautotags.items(): movie = movies[0] tags.sort(key=movie.find) first = movie.find(tags[0]) last = movie.find(tags[-1]) + len(tags[-1]) match = movie start = 0 end = len(movie) for m in movies[1:]: if m[start:end] != match: if not m.startswith(movie[:last]): start = first if not m.endswith(movie[first:]): end = last match = movie[start:end] if m[start:end] != match: match = '' break if match: self.tags[match] = set(tags) else: match = ' '.join(tags) if len(match) > 2 or match in realtags: self.tags[match] = set(tags) for tag in realtags: self.tags[tag] = set([tag]) return def buildAlphaNumericSortKey(self, x): ref = x[0] name = x[1] and x[1].getName(ref) if ref.flags & eServiceReference.mustDescent: return (0, name and name.lower() or '', -x[2]) return (1, name and name.lower() or '', -x[2]) def buildAlphaDateSortKey(self, x): ref = x[0] name = x[1] and x[1].getName(ref) if ref.flags & eServiceReference.mustDescent: return (0, name and name.lower() or '', x[2]) return (1, name and name.lower() or '', x[2]) def buildAlphaNumericFlatSortKey(self, x): ref = x[0] name = x[1] and x[1].getName(ref) if name and ref.flags & eServiceReference.mustDescent: p = os.path.split(name) if not p[1]: p = os.path.split(p[0]) name = p[1] return (1, name and name.lower() or '', -x[2]) def buildBeginTimeSortKey(self, x): ref = x[0] if ref.flags & eServiceReference.mustDescent: try: return (0, x[1] and -os.stat(ref.getPath()).st_mtime) except: return (1, -x[2]) return (1, -x[2]) def buildGroupwiseSortkey(self, x): ref = x[0] if ref.type >= eServiceReference.idUser: return self.buildAlphaNumericSortKey(x) else: return self.buildBeginTimeSortKey(x) def moveTo(self, serviceref): index = self.findService(serviceref) if index is not None: self.instance.moveSelectionTo(index) return True else: return False def moveDown(self): self.instance.moveSelection(self.instance.moveDown) def moveUp(self): self.instance.moveSelection(self.instance.moveUp) def moveToChar(self, char, lbl = None): self._char = char self._lbl = lbl if lbl: lbl.setText(self._char) lbl.visible = True self.moveToCharTimer = eTimer() self.moveToCharTimer.callback.append(self._moveToChrStr) self.moveToCharTimer.start(1000, True) def moveToString(self, char, lbl = None): self._char = self._char + char.upper() self._lbl = lbl if lbl: lbl.setText(self._char) lbl.visible = True self.moveToCharTimer = eTimer() self.moveToCharTimer.callback.append(self._moveToChrStr) self.moveToCharTimer.start(1000, True) def _moveToChrStr(self): currentIndex = self.instance.getCurrentIndex() found = False if currentIndex < len(self.list) - 1: itemsBelow = self.list[currentIndex + 1:] for index, item in enumerate(itemsBelow): ref = item[0] itemName = getShortName(item[1].getName(ref).upper(), ref) if len(self._char) == 1 and itemName.startswith(self._char): found = True self.instance.moveSelectionTo(index + currentIndex + 1) break elif len(self._char) > 1 and itemName.find(self._char) >= 0: found = True self.instance.moveSelectionTo(index + currentIndex + 1) break if found == False and currentIndex > 0: itemsAbove = self.list[1:currentIndex] for index, item in enumerate(itemsAbove): ref = item[0] itemName = getShortName(item[1].getName(ref).upper(), ref) if len(self._char) == 1 and itemName.startswith(self._char): found = True self.instance.moveSelectionTo(index + 1) break elif len(self._char) > 1 and itemName.find(self._char) >= 0: found = True self.instance.moveSelectionTo(index + 1) break self._char = '' if self._lbl: self._lbl.visible = False
class TimerList(HTMLComponent, GUIComponent, object): # # | <Name of the Timer> <Service> | # | <state> <orb.pos.> <start, end> | # def buildTimerEntry(self, timer, processed): width = self.l.getItemSize().width() res = [ None ] serviceName = timer.service_ref.getServiceName() serviceNameWidth = getTextBoundarySize(self.instance, self.serviceNameFont, self.l.getItemSize(), serviceName).width() if 200 > width - serviceNameWidth - self.iconWidth - self.iconMargin: serviceNameWidth = width - 200 - self.iconWidth - self.iconMargin res.append((eListboxPythonMultiContent.TYPE_TEXT, width - serviceNameWidth, 0, serviceNameWidth, self.rowSplit, 0, RT_HALIGN_RIGHT|RT_VALIGN_BOTTOM, serviceName)) res.append((eListboxPythonMultiContent.TYPE_TEXT, self.iconWidth + self.iconMargin, 0, width - serviceNameWidth - self.iconWidth - self.iconMargin, self.rowSplit, 2, RT_HALIGN_LEFT|RT_VALIGN_BOTTOM, timer.name)) begin = FuzzyTime(timer.begin) if timer.repeated: days = ( _("Mon"), _("Tue"), _("Wed"), _("Thu"), _("Fri"), _("Sat"), _("Sun") ) repeatedtext = [] flags = timer.repeated for x in (0, 1, 2, 3, 4, 5, 6): if (flags & 1 == 1): repeatedtext.append(days[x]) flags = flags >> 1 repeatedtext = ", ".join(repeatedtext) if self.iconRepeat: res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, self.iconMargin / 2, self.rowSplit + (self.itemHeight - self.rowSplit - self.iconHeight) / 2, self.iconWidth, self.iconHeight, self.iconRepeat)) else: repeatedtext = begin[0] # date if timer.justplay: text = repeatedtext + ((" %s "+ _("(ZAP)")) % (begin[1])) else: text = repeatedtext + ((" %s ... %s (%d " + _("mins") + ")") % (begin[1], FuzzyTime(timer.end)[1], (timer.end - timer.begin) / 60)) icon = None if not processed: if timer.state == TimerEntry.StateWaiting: state = _("waiting") icon = self.iconWait elif timer.state == TimerEntry.StatePrepared: state = _("about to start") icon = self.iconPrepared elif timer.state == TimerEntry.StateRunning: if timer.justplay: state = _("zapped") icon = self.iconZapped else: state = _("recording...") icon = self.iconRecording elif timer.state == TimerEntry.StateEnded: state = _("done!") icon = self.iconDone else: state = _("<unknown>") icon = None elif timer.disabled: state = _("disabled") icon = self.iconDisabled else: state = _("done!") icon = self.iconDone icon and res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHATEST, self.iconMargin / 2, (self.rowSplit - self.iconHeight) / 2, self.iconWidth, self.iconHeight, icon)) orbpos = self.getOrbitalPos(timer.service_ref) orbposWidth = getTextBoundarySize(self.instance, self.font, self.l.getItemSize(), orbpos).width() res.append((eListboxPythonMultiContent.TYPE_TEXT, self.satPosLeft, self.rowSplit, orbposWidth, self.itemHeight - self.rowSplit, 1, RT_HALIGN_LEFT|RT_VALIGN_TOP, orbpos)) res.append((eListboxPythonMultiContent.TYPE_TEXT, self.iconWidth + self.iconMargin, self.rowSplit, self.satPosLeft - self.iconWidth - self.iconMargin, self.itemHeight - self.rowSplit, 1, RT_HALIGN_LEFT|RT_VALIGN_TOP, state)) res.append((eListboxPythonMultiContent.TYPE_TEXT, self.satPosLeft + orbposWidth, self.rowSplit, width - self.satPosLeft - orbposWidth, self.itemHeight - self.rowSplit, 1, RT_HALIGN_RIGHT|RT_VALIGN_TOP, text)) return res def __init__(self, list): GUIComponent.__init__(self) self.l = eListboxPythonMultiContent() self.l.setBuildFunc(self.buildTimerEntry) self.serviceNameFont = gFont("Regular", 20) self.font = gFont("Regular", 18) self.eventNameFont = gFont("Regular", 18) self.l.setList(list) self.itemHeight = 50 self.rowSplit = 25 self.iconMargin = 4 self.satPosLeft = 160 self.iconWait = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/timer_wait.png")) #currently intended that all icons have the same size self.iconWidth = self.iconWait.size().width() self.iconHeight = self.iconWait.size().height() self.iconRecording = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/timer_rec.png")) self.iconPrepared = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/timer_prep.png")) self.iconDone = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/timer_done.png")) self.iconRepeat = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/timer_rep.png")) self.iconZapped = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/timer_zap.png")) self.iconDisabled = LoadPixmap(resolveFilename(SCOPE_SKIN_IMAGE, "skin_default/icons/timer_off.png")) def applySkin(self, desktop, parent): def itemHeight(value): self.itemHeight = int(value) def setServiceNameFont(value): self.serviceNameFont = parseFont(value, ((1,1),(1,1))) def setEventNameFont(value): self.eventNameFont = parseFont(value, ((1,1),(1,1))) def setFont(value): self.font = parseFont(value, ((1,1),(1,1))) def rowSplit(value): self.rowSplit = int(value) def iconMargin(value): self.iconMargin = int(value) def satPosLeft(value): self.satPosLeft = int(value) for (attrib, value) in list(self.skinAttributes): try: locals().get(attrib)(value) self.skinAttributes.remove((attrib, value)) except: pass self.l.setItemHeight(self.itemHeight) self.l.setFont(0, self.serviceNameFont) self.l.setFont(1, self.font) self.l.setFont(2, self.eventNameFont) return GUIComponent.applySkin(self, desktop, parent) def getCurrent(self): cur = self.l.getCurrentSelection() return cur and cur[0] GUI_WIDGET = eListbox def postWidgetCreate(self, instance): instance.setContent(self.l) self.instance = instance instance.setWrapAround(True) def moveToIndex(self, index): self.instance.moveSelectionTo(index) def getCurrentIndex(self): return self.instance.getCurrentIndex() currentIndex = property(getCurrentIndex, moveToIndex) currentSelection = property(getCurrent) def moveDown(self): self.instance.moveSelection(self.instance.moveDown) def invalidate(self): self.l.invalidate() def entryRemoved(self, idx): self.l.entryRemoved(idx) def getOrbitalPos(self, ref): refstr = '' if hasattr(ref, 'sref'): refstr = str(ref.sref) else: refstr = str(ref) refstr = refstr and GetWithAlternative(refstr) if '%3a//' in refstr: return "%s" % _("Stream") op = int(refstr.split(':', 10)[6][:-4] or "0",16) if op == 0xeeee: return "%s" % _("DVB-T") if op == 0xffff: return "%s" % _("DVB-C") direction = 'E' if op > 1800: op = 3600 - op direction = 'W' return ("%d.%d\xc2\xb0%s") % (op // 10, op % 10, direction)
class AutoTimerList(MenuList): """Defines a simple Component to show Timer name""" # # | <timername> <timespan> | line 'EventNameFont' # | <timeframe> <days> | line 'DayNameFont' # | <servicename> | line 'ServiceNameFont' # def __init__(self, entries): MenuList.__init__(self, entries, False, content = eListboxPythonMultiContent) self.l.setBuildFunc(self.buildListboxEntry) try: png = resolveFilename(SCOPE_ACTIVE_SKIN, "icons/lock_off.png") except: png = resolveFilename(SCOPE_CURRENT_SKIN, "skin-default/icons/lock_off.png") self.iconDisabled = LoadPixmap(cached=True, path=png) #currently intended that all icons have the same size try: png = resolveFilename(SCOPE_ACTIVE_SKIN, "icons/lock_on.png") except: png = resolveFilename(SCOPE_CURRENT_SKIN, "skin-default/icons/lock_on.png") self.iconEnabled = LoadPixmap(cached=True, path=png) try: png = resolveFilename(SCOPE_ACTIVE_SKIN, "icons/timer_rec.png") except: png = resolveFilename(SCOPE_CURRENT_SKIN, "skin-default/icons/timer_rec.png") self.iconRecording = LoadPixmap(cached=True, path=png) try: png = resolveFilename(SCOPE_ACTIVE_SKIN, "icons/timer_zap.png") except: png = resolveFilename(SCOPE_CURRENT_SKIN, "skin-default/icons/timer_zap.png") self.iconZapped = LoadPixmap(cached=True, path=png) self.ServiceNameFont = gFont("Regular", 20) self.EventNameFont = gFont("Regular", 20) self.DayNameFont = gFont("Regular", 18) self.itemHeight = 75 self.rowHeight = 24 self.rowSplit1 = 26 self.rowSplit2 = 47 self.statusIconWidth = self.iconEnabled.size().width() self.statusIconHeight = self.iconEnabled.size().height() self.typeIconWidth = self.iconRecording.size().width() self.typeIconHeight = self.iconRecording.size().height() self.iconMargin = 2 def applySkin(self, desktop, parent): def itemHeight(value): self.itemHeight = int(value) def ServiceNameFont(value): self.ServiceNameFont = parseFont(value, ((1,1),(1,1))) def EventNameFont(value): self.EventNameFont = parseFont(value, ((1,1),(1,1))) def DayNameFont(value): self.DayNameFont = parseFont(value, ((1,1),(1,1))) def rowHeight(value): self.rowHeight = int(value) def rowSplit1(value): self.rowSplit1 = int(value) def rowSplit2(value): self.rowSplit2 = int(value) def iconMargin(value): self.iconMargin = int(value) for (attrib, value) in list(self.skinAttributes): try: locals().get(attrib)(value) self.skinAttributes.remove((attrib, value)) except: pass self.l.setItemHeight(self.itemHeight) self.l.setFont(0, self.ServiceNameFont) self.l.setFont(1, self.EventNameFont) self.l.setFont(2, self.DayNameFont) return MenuList.applySkin(self, desktop, parent) def buildListboxEntry(self, timer): if not timer.enabled: icon = self.iconDisabled else: icon = self.iconEnabled if timer.justplay: rectypeicon = self.iconZapped else: rectypeicon = self.iconRecording height = self.l.getItemSize().height() width = self.l.getItemSize().width() iconMargin = self.iconMargin statusIconHeight = self.statusIconHeight statusIconWidth = self.statusIconWidth typeIconHeight = self.typeIconHeight typeIconWidth = self.typeIconWidth rowHeight = self.rowHeight rowSplit1 = self.rowSplit1 rowSplit2 = self.rowSplit2 channel = [] for t in timer.services: channel.append(ServiceReference(t).getServiceName()) if len(channel) >0 : channel = ", ".join(channel) else: channel = _('All channels') res = [ None ] if icon: if skinparms: x, y, w, h = parameters.get("AutotimerEnabledIcon",(iconMargin, 0, statusIconHeight, statusIconWidth)) else: x, y, w, h = (iconMargin, 0, statusIconHeight, statusIconWidth) res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, x, y, w, h, icon)) if rectypeicon: if skinparms: x, y, w, h = parameters.get("AutotimerRecordIcon",(iconMargin+statusIconWidth+iconMargin, 3, statusIconHeight, typeIconWidth)) else: x, y, w, h = (iconMargin+statusIconWidth+iconMargin, 3, statusIconHeight, typeIconWidth) res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, x, y, w, h, rectypeicon)) if timer.hasTimespan(): nowt = time() now = localtime(nowt) begintime = int(mktime((now.tm_year, now.tm_mon, now.tm_mday, timer.timespan[0][0], timer.timespan[0][1], 0, now.tm_wday, now.tm_yday, now.tm_isdst))) endtime = int(mktime((now.tm_year, now.tm_mon, now.tm_mday, timer.timespan[1][0], timer.timespan[1][1], 0, now.tm_wday, now.tm_yday, now.tm_isdst))) timespan = ((" %s ... %s") % (FuzzyTime(begintime)[1], FuzzyTime(endtime)[1])) else: timespan = _(" Any time") res.append((eListboxPythonMultiContent.TYPE_TEXT, float(width)/10*4.5, 2, width-float(width)/10*4.5, rowHeight, 1, RT_HALIGN_RIGHT|RT_VALIGN_BOTTOM, timespan)) if TextBoundary: timespanWidth = getTextBoundarySize(self.instance, self.EventNameFont, self.l.getItemSize(), timespan).width() else: timespanWidth = float(width)/10*2 res.append((eListboxPythonMultiContent.TYPE_TEXT, statusIconWidth+typeIconWidth+iconMargin*3, 2, width-statusIconWidth-typeIconWidth-iconMargin*3- timespanWidth, rowHeight, 1, RT_HALIGN_LEFT|RT_VALIGN_BOTTOM, timer.name)) if timer.hasTimeframe(): begin = strftime("%a, %d %b", localtime(timer.getTimeframeBegin())) end = strftime("%a, %d %b", localtime(timer.getTimeframeEnd())) timeframe = (("%s ... %s") % (begin, end)) res.append((eListboxPythonMultiContent.TYPE_TEXT, iconMargin, rowSplit1, float(width)/10*4.5, rowHeight, 2, RT_HALIGN_LEFT|RT_VALIGN_TOP, timeframe)) if timer.include[3]: total = len(timer.include[3]) count = 0 days = [] while count+1 <= total: day = timer.include[3][count] day = { '0': _("Mon"), '1': _("Tue"), '2': _("Wed"), '3': _("Thur"), '4': _("Fri"), '5': _("Sat"), '6': _("Sun"), "weekend": _("Weekend"), "weekday": _("Weekday") }[day] days.append(day) count += 1 days = ', '.join(days) else: days = _("Everyday") res.append((eListboxPythonMultiContent.TYPE_TEXT, float(width)/10*5.5, rowSplit1, width-float(width)/10*5.5, rowHeight, 2, RT_HALIGN_RIGHT|RT_VALIGN_TOP, days)) res.append((eListboxPythonMultiContent.TYPE_TEXT, iconMargin, rowSplit2, width-(iconMargin*2), rowHeight, 0, RT_HALIGN_LEFT|RT_VALIGN_TOP, channel)) try: devide = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, "div-h.png")) except: devide = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/div-h.png")) res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, 0, height-2, width, 2, devide)) return res def getCurrent(self): cur = self.l.getCurrentSelection() return cur and cur[0] def moveToEntry(self, entry): if entry is None: return idx = 0 for x in self.list: if x[0] == entry: self.instance.moveSelectionTo(idx) break idx += 1
class VirtualKeyBoard(Screen): def __init__(self, session, title="", **kwargs): Screen.__init__(self, session) self.setTitle(_("Virtual keyboard")) self.keys_list = [] self.shiftkeys_list = [] self.lang = language.getLanguage() self.nextLang = None self.shiftMode = False self.selectedKey = 0 self.smsChar = None self.sms = NumericalTextInput(self.smsOK) self.key_bg = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_bg.png")) self.key_sel = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_sel.png")) self.key_backspace = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_backspace.png")) self.key_all = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_all.png")) self.key_clr = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_clr.png")) self.key_esc = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_esc.png")) self.key_ok = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_ok.png")) self.key_shift = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_shift.png")) self.key_shift_sel = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_shift_sel.png")) self.key_space = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_space.png")) self.key_left = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_left.png")) self.key_right = LoadPixmap(path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/vkey_right.png")) self.keyImages = { "BACKSPACE": self.key_backspace, "ALL": self.key_all, "EXIT": self.key_esc, "OK": self.key_ok, "SHIFT": self.key_shift, "SPACE": self.key_space, "LEFT": self.key_left, "RIGHT": self.key_right } self.keyImagesShift = { "BACKSPACE": self.key_backspace, "CLEAR": self.key_clr, "EXIT": self.key_esc, "OK": self.key_ok, "SHIFT": self.key_shift_sel, "SPACE": self.key_space, "LEFT": self.key_left, "RIGHT": self.key_right } self["country"] = StaticText("") self["header"] = Label(title) self["text"] = Input(currPos=len(kwargs.get("text", "").decode("utf-8",'ignore')), allMarked=False, **kwargs) self["list"] = VirtualKeyBoardList([]) self["actions"] = NumberActionMap(["OkCancelActions", "WizardActions", "ColorActions", "KeyboardInputActions", "InputBoxActions", "InputAsciiActions"], { "gotAsciiCode": self.keyGotAscii, "ok": self.okClicked, "cancel": self.exit, "left": self.left, "right": self.right, "up": self.up, "down": self.down, "red": self.exit, "green": self.ok, "yellow": self.switchLang, "blue": self.shiftClicked, "deleteBackward": self.backClicked, "deleteForward": self.forwardClicked, "back": self.exit, "pageUp": self.cursorRight, "pageDown": self.cursorLeft, "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, }, -2) self.setLang() self.onExecBegin.append(self.setKeyboardModeAscii) self.onLayoutFinish.append(self.buildVirtualKeyBoard) self.onClose.append(self.__onClose) def __onClose(self): self.sms.timer.stop() def switchLang(self): self.lang = self.nextLang self.setLang() self.buildVirtualKeyBoard() def setLang(self): if self.lang == 'cs_CZ': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"ú", u"+"], [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ů", u"@", u"#"], [u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL"], [u"SHIFT", u"SPACE", u"ě", u"š", u"č", u"ř", u"ž", u"ý", u"á", u"í", u"é", u"OK"]] self.shiftkeys_list = [ [u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE"], [u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"ť", u"*"], [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"ň", u"ď", u"'"], [u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR"], [u"SHIFT", u"SPACE", u"?", u"\\", u"Č", u"Ř", u"Š", u"Ž", u"Ú", u"Á", u"É", u"OK"]] self.nextLang = 'de_DE' elif self.lang == 'de_DE': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"ü", u"+"], [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ö", u"ä", u"#"], [u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL"], [u"SHIFT", u"SPACE", u"@", u"ß", u"OK", u"LEFT", u"RIGHT"]] self.shiftkeys_list = [ [u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE"], [u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"Ü", u"*"], [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"Ö", u"Ä", u"'"], [u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR"], [u"SHIFT", u"SPACE", u"?", u"\\", u"OK", u"LEFT", u"RIGHT"]] self.nextLang = 'el_GR' elif self.lang == 'el_GR': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"=", u"ς", u"ε", u"ρ", u"τ", u"υ", u"θ", u"ι", u"ο", u"π", u"[", u"]"], [u"α", u"σ", u"δ", u"φ", u"γ", u"η", u"ξ", u"κ", u"λ", u";", u"'", u"-"], [u"\\", u"ζ", u"χ", u"ψ", u"ω", u"β", u"ν", u"μ", u",", ".", u"/", u"ALL"], [u"SHIFT", u"SPACE", u"ά", u"έ", u"ή", u"ί", u"ό", u"ύ", u"ώ", u"ϊ", u"ϋ", u"OK"]] self.shiftkeys_list = [ [u"EXIT", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"*", u"(", u")", u"BACKSPACE"], [u"+", u"€", u"Ε", u"Ρ", u"Τ", u"Υ", u"Θ", u"Ι", u"Ο", u"Π", u"{", u"}"], [u"Α", u"Σ", u"Δ", u"Φ", u"Γ", u"Η", u"Ξ", u"Κ", u"Λ", u":", u'"', u"_"], [u"|", u"Ζ", u"Χ", u"Ψ", u"Ω", u"Β", u"Ν", u"Μ", u"<", u">", u"?", u"CLEAR"], [u"SHIFT", u"SPACE", u"Ά", u"Έ", u"Ή", u"Ί", u"Ό", u"Ύ", u"Ώ", u"Ϊ", u"Ϋ", u"OK"]] self.nextLang = 'es_ES' elif self.lang == 'es_ES': #still missing keys (u"ùÙ") self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"ú", u"+"], [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ó", u"á", u"#"], [u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL"], [u"SHIFT", u"SPACE", u"@", u"Ł", u"ŕ", u"é", u"č", u"í", u"ě", u"ń", u"ň", u"OK"]] self.shiftkeys_list = [ [u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE"], [u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"Ú", u"*"], [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"Ó", u"Á", u"'"], [u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR"], [u"SHIFT", u"SPACE", u"?", u"\\", u"Ŕ", u"É", u"Č", u"Í", u"Ě", u"Ń", u"Ň", u"OK"]] self.nextLang = 'fa_IR' elif self.lang == 'fa_IR': self.keys_list = [ [u"EXIT", u"\u06F1", u"\u06F2", u"\u06F3", u"\u06F4", u"\u06F5", u"\u06F6", u"\u06F7", u"\u06F8", u"\u06F9", u"\u06F0", u"BACKSPACE"], [u"\u0636", u"\u0635", u"\u062B", u"\u0642", u"\u0641", u"\u063A", u"\u0639", u"\u0647", u"\u062E", u"\u062D", u"-", u"\u062C"], [u"\u0634", u"\u0633", u"\u06CC", u"\u0628", u"\u0644", u"\u0627", u"\u062A", u"\u0646", u"\u0645", u"\u06A9", u"\u06AF", u"\u067E"], [u"<", u"\u0638", u"\u0637", u"\u0632", u"\u0631", u"\u0630", u"\u062F", u"\u0626", u"\u0648", ".", u"/", u"ALL"], [u"SHIFT", u"SPACE", u"OK", u"LEFT", u"RIGHT", u"*"]] self.shiftkeys_list = [ [u"EXIT", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"(", u")", u"=", u"BACKSPACE"], [u"\u0636", u"\u0635", u"\u062B", u"\u0642", u"\u060C", u"\u061B", u"\u0639", u"\u0647", u"\u062E", u"\u062D", u"+", u"\u0686"], [u"\u0634", u"\u0633", u"\u06CC", u"\u0628", u"\u06C0", u"\u0622", u"\u062A", u"\u0646", u"\u0645", u"?", u'"', u"|"], [u">", u"\u0629", u"\u064A", u"\u0698", u"\u0624", u"\u0625", u"\u0623", u"\u0621", u";", u":", u"\u061F", u"CLEAR"], [u"SHIFT", u"SPACE", u"OK", u"LEFT", u"RIGHT", u"~"]] self.nextLang = 'fi_FI' elif self.lang == 'fi_FI': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"é", u"+"], [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ö", u"ä", u"#"], [u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL"], [u"SHIFT", u"SPACE", u"@", u"ß", u"ĺ", u"OK", u"LEFT", u"RIGHT"]] self.shiftkeys_list = [ [u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE"], [u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"É", u"*"], [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"Ö", u"Ä", u"'"], [u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR"], [u"SHIFT", u"SPACE", u"?", u"\\", u"Ĺ", u"OK", u"LEFT", u"RIGHT"]] self.nextLang = 'fr_FR' elif self.lang == 'fr_FR': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"a", u"z", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"é", u"è"], [u"q", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"m", u"ê", u"ë"], [u"<", u"w", u"x", u"c", u"v", u"b", u"n", u",", u";", u":", u"=", u"ALL"], [u"SHIFT", u"SPACE", u"ù", u"â", u"ï", u"ô", u"ç", u"#", u"-", u"OK", u"LEFT", u"RIGHT"]] self.shiftkeys_list = [ [u"EXIT", u"&", u'@', u'"', u"€", u"§", u"!", u"ç", u"(", u")", u"_", u"BACKSPACE"], [u"A", u"Z", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"É", u"È"], [u"Q", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"M", u"Ê", u"Ë"], [u">", u"W", u"X", u"C", u"V", u"B", u"N", u"?", u".", u"+", u"~", u"CLEAR"], [u"SHIFT", u"SPACE", u"Ù", u"Â", u"Ï", u"Ô", u"°", u"/",u"\\", u"OK", u"LEFT", u"RIGHT"]] self.nextLang = 'lv_LV' elif self.lang == 'lv_LV': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"q", u"w", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"-", u"š"], [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u";", u"'", u"ū"], [u"<", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", u".", u"ž", u"ALL"], [u"SHIFT", u"SPACE", u"ā", u"č", u"ē", u"ģ", u"ī", u"ķ", u"ļ", u"ņ", u"LEFT", u"RIGHT"]] self.shiftkeys_list = [ [u"EXIT", u"!", u"@", u"$", u"*", u"(", u")", u"_", u"=", u"/", u"\\", u"BACKSPACE"], [u"Q", u"W", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"+", u"Š"], [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u":", u'"', u"Ū"], [u">", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u"#", u"?", u"Ž", u"CLEAR"], [u"SHIFT", u"SPACE", u"Ā", u"Č", u"Ē", u"Ģ", u"Ī", u"Ķ", u"Ļ", u"Ņ", u"LEFT", u"RIGHT"]] self.nextLang = 'pl_PL' elif self.lang == 'pl_PL': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"q", u"w", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"-", u"["], [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u";", u"'", u"\\"], [u"<", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"/", u"ALL"], [u"SHIFT", u"SPACE", u"ą", u"ć", u"ę", u"ł", u"ń", u"ó", u"ś", u"ź", u"ż", u"OK"]] self.shiftkeys_list = [ [u"EXIT", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"(", u")", u"=", u"BACKSPACE"], [u"Q", u"W", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"*", u"]"], [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"?", u'"', u"|"], [u">", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR"], [u"SHIFT", u"SPACE", u"Ą", u"Ć", u"Ę", u"Ł", u"Ń", u"Ó", u"Ś", u"Ź", u"Ż", u"OK"]] self.nextLang = 'ru_RU' elif self.lang == 'ru_RU': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"а", u"б", u"в", u"г", u"д", u"е", u"ё", u"ж", u"з", u"и", u"й", u"+"], [u"к", u"л", u"м", u"н", u"о", u"п", u"р", u"с", u"т", u"у", u"ф", u"#"], [u"<", u"х", u"ц", u"ч", u"ш", u"щ", u"ъ", u"ы", u",", u".", u"-", u"ALL"], [u"SHIFT", u"SPACE", u"@", u"ь", u"э", u"ю", u"я", u"OK", u"LEFT", u"RIGHT"]] self.shiftkeys_list = [ [u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE"], [u"А", u"Б", u"В", u"Г", u"Д", u"Е", u"Ё", u"Ж", u"З", u"И", u"Й", u"*"], [u"К", u"Л", u"М", u"Н", u"О", u"П", u"Р", u"С", u"Т", u"У", u"Ф", u"'"], [u">", u"Х", u"Ц", u"Ч", u"Ш", u"Щ", u"Ъ", u"Ы", u";", u":", u"_", u"CLEAR"], [u"SHIFT", u"SPACE", u"?", u"\\", u"Ь", u"Э", u"Ю", u"Я", u"OK", u"LEFT", u"RIGHT"]] self.nextLang = 'sk_SK' elif self.lang =='sk_SK': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"ú", u"+"], [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ľ", u"@", u"#"], [u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL"], [u"SHIFT", u"SPACE", u"š", u"č", u"ž", u"ý", u"á", u"í", u"é", u"OK", u"LEFT", u"RIGHT"]] self.shiftkeys_list = [ [u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE"], [u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"ť", u"*"], [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"ň", u"ď", u"'"], [u"Á", u"É", u"Ď", u"Í", u"Ý", u"Ó", u"Ú", u"Ž", u"Š", u"Č", u"Ť", u"Ň"], [u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR"], [u"SHIFT", u"SPACE", u"?", u"\\", u"ä", u"ö", u"ü", u"ô", u"ŕ", u"ĺ", u"OK"]] self.nextLang = 'sv_SE' elif self.lang == 'sv_SE': self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"q", u"w", u"e", u"r", u"t", u"z", u"u", u"i", u"o", u"p", u"é", u"+"], [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u"ö", u"ä", u"#"], [u"<", u"y", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"-", u"ALL"], [u"SHIFT", u"SPACE", u"@", u"ß", u"ĺ", u"OK", u"LEFT", u"RIGHT"]] self.shiftkeys_list = [ [u"EXIT", u"!", u'"', u"§", u"$", u"%", u"&", u"/", u"(", u")", u"=", u"BACKSPACE"], [u"Q", u"W", u"E", u"R", u"T", u"Z", u"U", u"I", u"O", u"P", u"É", u"*"], [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"Ö", u"Ä", u"'"], [u">", u"Y", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR"], [u"SHIFT", u"SPACE", u"?", u"\\", u"Ĺ", u"OK", u"LEFT", u"RIGHT"]] self.nextLang = 'th_TH' elif self.lang == 'th_TH': self.keys_list = [[u"EXIT", "\xe0\xb9\x85", "\xe0\xb8\xa0", "\xe0\xb8\x96", "\xe0\xb8\xb8", "\xe0\xb8\xb6", "\xe0\xb8\x84", "\xe0\xb8\x95", "\xe0\xb8\x88", "\xe0\xb8\x82", "\xe0\xb8\x8a", u"BACKSPACE"], ["\xe0\xb9\x86", "\xe0\xb9\x84", "\xe0\xb8\xb3", "\xe0\xb8\x9e", "\xe0\xb8\xb0", "\xe0\xb8\xb1", "\xe0\xb8\xb5", "\xe0\xb8\xa3", "\xe0\xb8\x99", "\xe0\xb8\xa2", "\xe0\xb8\x9a", "\xe0\xb8\xa5"], ["\xe0\xb8\x9f", "\xe0\xb8\xab", "\xe0\xb8\x81", "\xe0\xb8\x94", "\xe0\xb9\x80", "\xe0\xb9\x89", "\xe0\xb9\x88", "\xe0\xb8\xb2", "\xe0\xb8\xaa", "\xe0\xb8\xa7", "\xe0\xb8\x87", "\xe0\xb8\x83"], ["\xe0\xb8\x9c", "\xe0\xb8\x9b", "\xe0\xb9\x81", "\xe0\xb8\xad", "\xe0\xb8\xb4", "\xe0\xb8\xb7", "\xe0\xb8\x97", "\xe0\xb8\xa1", "\xe0\xb9\x83", "\xe0\xb8\x9d", "", u"ALL"], [u"SHIFT", u"SPACE", u"OK", u"LEFT", u"RIGHT"]] self.shiftkeys_list = [[u"EXIT", "\xe0\xb9\x91", "\xe0\xb9\x92", "\xe0\xb9\x93", "\xe0\xb9\x94", "\xe0\xb8\xb9", "\xe0\xb9\x95", "\xe0\xb9\x96", "\xe0\xb9\x97", "\xe0\xb9\x98", "\xe0\xb9\x99", u"BACKSPACE"], ["\xe0\xb9\x90", "", "\xe0\xb8\x8e", "\xe0\xb8\x91", "\xe0\xb8\x98", "\xe0\xb9\x8d", "\xe0\xb9\x8a", "\xe0\xb8\x93", "\xe0\xb8\xaf", "\xe0\xb8\x8d", "\xe0\xb8\x90", "\xe0\xb8\x85"], ["\xe0\xb8\xa4", "\xe0\xb8\x86", "\xe0\xb8\x8f", "\xe0\xb9\x82", "\xe0\xb8\x8c", "\xe0\xb9\x87", "\xe0\xb9\x8b", "\xe0\xb8\xa9", "\xe0\xb8\xa8", "\xe0\xb8\x8b", "", "\xe0\xb8\xbf"], ["", "", "\xe0\xb8\x89", "\xe0\xb8\xae", "\xe0\xb8\xba", "\xe0\xb9\x8c", "", "\xe0\xb8\x92", "\xe0\xb8\xac", "\xe0\xb8\xa6", "", u"CLEAR"], [u"SHIFT", u"SPACE", u"OK", u"LEFT", u"RIGHT"]] self.nextLang = 'en_EN' else: self.keys_list = [ [u"EXIT", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"0", u"BACKSPACE"], [u"q", u"w", u"e", u"r", u"t", u"y", u"u", u"i", u"o", u"p", u"-", u"["], [u"a", u"s", u"d", u"f", u"g", u"h", u"j", u"k", u"l", u";", u"'", u"\\"], [u"<", u"z", u"x", u"c", u"v", u"b", u"n", u"m", u",", ".", u"/", u"ALL"], [u"SHIFT", u"SPACE", u"OK", u"LEFT", u"RIGHT", u"*"]] self.shiftkeys_list = [ [u"EXIT", u"!", u"@", u"#", u"$", u"%", u"^", u"&", u"(", u")", u"=", u"BACKSPACE"], [u"Q", u"W", u"E", u"R", u"T", u"Y", u"U", u"I", u"O", u"P", u"+", u"]"], [u"A", u"S", u"D", u"F", u"G", u"H", u"J", u"K", u"L", u"?", u'"', u"|"], [u">", u"Z", u"X", u"C", u"V", u"B", u"N", u"M", u";", u":", u"_", u"CLEAR"], [u"SHIFT", u"SPACE", u"OK", u"LEFT", u"RIGHT", u"~"]] self.lang = 'en_EN' self.nextLang = 'cs_CZ' self["country"].setText(self.lang) self.max_key=47+len(self.keys_list[4]) def virtualKeyBoardEntryComponent(self, keys): w, h = skin.parameters.get("VirtualKeyboard",(45, 45)) key_bg_width = self.key_bg and self.key_bg.size().width() or w key_images = self.shiftMode and self.keyImagesShift or self.keyImages res = [keys] text = [] x = 0 for key in keys: png = key_images.get(key, None) if png: width = png.size().width() res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, h), png=png)) else: width = key_bg_width res.append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, h), png=self.key_bg)) text.append(MultiContentEntryText(pos=(x, 0), size=(width, h), font=0, text=key.encode("utf-8"), flags=RT_HALIGN_CENTER | RT_VALIGN_CENTER)) x += width return res + text def buildVirtualKeyBoard(self): self.previousSelectedKey = None self.list = [] for keys in self.shiftMode and self.shiftkeys_list or self.keys_list: self.list.append(self.virtualKeyBoardEntryComponent(keys)) self.markSelectedKey() def markSelectedKey(self): w, h = skin.parameters.get("VirtualKeyboard",(45, 45)) if self.previousSelectedKey is not None: self.list[self.previousSelectedKey /12] = self.list[self.previousSelectedKey /12][:-1] width = self.key_sel.size().width() x = self.list[self.selectedKey/12][self.selectedKey % 12 + 1][1] self.list[self.selectedKey / 12].append(MultiContentEntryPixmapAlphaTest(pos=(x, 0), size=(width, h), png=self.key_sel)) self.previousSelectedKey = self.selectedKey self["list"].setList(self.list) def backClicked(self): self["text"].deleteBackward() def forwardClicked(self): self["text"].deleteForward() def shiftClicked(self): self.smsChar = None self.shiftMode = not self.shiftMode self.buildVirtualKeyBoard() def okClicked(self): self.smsChar = None text = (self.shiftMode and self.shiftkeys_list or self.keys_list)[self.selectedKey / 12][self.selectedKey % 12].encode("UTF-8") if text == "EXIT": self.close(None) elif text == "BACKSPACE": self["text"].deleteBackward() elif text == "ALL": self["text"].markAll() elif text == "CLEAR": self["text"].deleteAllChars() self["text"].update() elif text == "SHIFT": self.shiftClicked() elif text == "SPACE": self["text"].char(" ".encode("UTF-8")) elif text == "OK": self.close(self["text"].getText()) elif text == "LEFT": self["text"].left() elif text == "RIGHT": self["text"].right() else: self["text"].char(text) def ok(self): self.close(self["text"].getText()) def exit(self): self.close(None) def cursorRight(self): self["text"].right() def cursorLeft(self): self["text"].left() def left(self): self.smsChar = None self.selectedKey = self.selectedKey / 12 * 12 + (self.selectedKey + 11) % 12 if self.selectedKey > self.max_key: self.selectedKey = self.max_key self.markSelectedKey() def right(self): self.smsChar = None self.selectedKey = self.selectedKey / 12 * 12 + (self.selectedKey + 1) % 12 if self.selectedKey > self.max_key: self.selectedKey = self.selectedKey / 12 * 12 self.markSelectedKey() def up(self): self.smsChar = None self.selectedKey -= 12 if self.selectedKey < 0: self.selectedKey = self.max_key / 12 * 12 + self.selectedKey % 12 if self.selectedKey > self.max_key: self.selectedKey -= 12 self.markSelectedKey() def down(self): self.smsChar = None self.selectedKey += 12 if self.selectedKey > self.max_key: self.selectedKey %= 12 self.markSelectedKey() def keyNumberGlobal(self, number): self.smsChar = self.sms.getKey(number) self.selectAsciiKey(self.smsChar) def smsOK(self): if self.smsChar and self.selectAsciiKey(self.smsChar): print "pressing ok now" self.okClicked() def keyGotAscii(self): self.smsChar = None if self.selectAsciiKey(str(unichr(getPrevAsciiCode()).encode('utf-8'))): self.okClicked() def selectAsciiKey(self, char): if char == " ": char = "SPACE" for keyslist in (self.shiftkeys_list, self.keys_list): selkey = 0 for keys in keyslist: for key in keys: if key == char: self.selectedKey = selkey if self.shiftMode != (keyslist is self.shiftkeys_list): self.shiftMode = not self.shiftMode self.buildVirtualKeyBoard() else: self.markSelectedKey() return True selkey += 1 return False
class TimerList(HTMLComponent, GUIComponent, object): def buildTimerEntry(self, timer, processed): height = self.l.getItemSize().height() width = self.l.getItemSize().width() res = [None] serviceName = timer.service_ref.getServiceName() serviceNameWidth = getTextBoundarySize(self.instance, self.serviceNameFont, self.l.getItemSize(), serviceName).width() if 200 > width - serviceNameWidth - self.iconWidth - self.iconMargin: serviceNameWidth = width - 200 - self.iconWidth - self.iconMargin res.append((eListboxPythonMultiContent.TYPE_TEXT, width - serviceNameWidth, 0, serviceNameWidth, self.rowSplit, 0, RT_HALIGN_RIGHT | RT_VALIGN_BOTTOM, serviceName)) res.append((eListboxPythonMultiContent.TYPE_TEXT, self.iconWidth + self.iconMargin, 0, width - serviceNameWidth - self.iconWidth - self.iconMargin, self.rowSplit, 2, RT_HALIGN_LEFT | RT_VALIGN_BOTTOM, timer.name)) begin = FuzzyTime(timer.begin) if timer.repeated: days = (_('Mon'), _('Tue'), _('Wed'), _('Thu'), _('Fri'), _('Sat'), _('Sun')) repeatedtext = [] flags = timer.repeated for x in (0, 1, 2, 3, 4, 5, 6): if flags & 1 == 1: repeatedtext.append(days[x]) flags >>= 1 if repeatedtext == [_('Mon'), _('Tue'), _('Wed'), _('Thu'), _('Fri'), _('Sat'), _('Sun')]: repeatedtext = _('Everyday') elif repeatedtext == [_('Mon'), _('Tue'), _('Wed'), _('Thu'), _('Fri')]: repeatedtext = _('Weekday') elif repeatedtext == [_('Sat'), _('Sun')]: repeatedtext = _('Weekend') else: repeatedtext = ', '.join(repeatedtext) if self.iconRepeat: res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, self.iconMargin / 2, self.rowSplit + (self.itemHeight - self.rowSplit - self.iconHeight) / 2, self.iconWidth, self.iconHeight, self.iconRepeat)) else: repeatedtext = begin[0] if timer.justplay: if timer.end > timer.begin + 3: text = repeatedtext + (' %s ... %s (' + _('ZAP') + ', %d ' + _('mins') + ')') % (begin[1], FuzzyTime(timer.end)[1], (timer.end - timer.begin) / 60) else: text = repeatedtext + (' %s (' + _('ZAP') + ')') % begin[1] else: text = repeatedtext + (' %s ... %s (%d ' + _('mins') + ')') % (begin[1], FuzzyTime(timer.end)[1], (timer.end - timer.begin) / 60) icon = None if not processed: if timer.state == TimerEntry.StateWaiting: state = _('waiting') if timer.isAutoTimer: icon = self.iconAutoTimer else: icon = self.iconWait elif timer.state == TimerEntry.StatePrepared: state = _('about to start') icon = self.iconPrepared elif timer.state == TimerEntry.StateRunning: if timer.justplay: state = _('zapped') icon = self.iconZapped else: state = _('recording...') icon = self.iconRecording elif timer.state == TimerEntry.StateEnded: state = _('done!') icon = self.iconDone else: state = _('<unknown>') icon = None elif timer.disabled: state = _('disabled') icon = self.iconDisabled elif timer.failed: state = _('failed') icon = self.iconFailed else: state = _('done!') icon = self.iconDone icon and res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, self.iconMargin / 2, (self.rowSplit - self.iconHeight) / 2, self.iconWidth, self.iconHeight, icon)) orbpos = self.getOrbitalPos(timer.service_ref) orbposWidth = getTextBoundarySize(self.instance, self.font, self.l.getItemSize(), orbpos).width() res.append((eListboxPythonMultiContent.TYPE_TEXT, self.satPosLeft, self.rowSplit, orbposWidth, self.itemHeight - self.rowSplit, 1, RT_HALIGN_LEFT | RT_VALIGN_TOP, orbpos)) res.append((eListboxPythonMultiContent.TYPE_TEXT, self.iconWidth + self.iconMargin, self.rowSplit, self.satPosLeft - self.iconWidth - self.iconMargin, self.itemHeight - self.rowSplit, 1, RT_HALIGN_LEFT | RT_VALIGN_TOP, state)) res.append((eListboxPythonMultiContent.TYPE_TEXT, self.satPosLeft + orbposWidth, self.rowSplit, width - self.satPosLeft - orbposWidth, self.itemHeight - self.rowSplit, 1, RT_HALIGN_RIGHT | RT_VALIGN_TOP, text)) line = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, 'div-h.png')) res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, 0, height - 2, width, 2, line)) return res def __init__(self, list): GUIComponent.__init__(self) self.l = eListboxPythonMultiContent() self.l.setBuildFunc(self.buildTimerEntry) self.serviceNameFont = gFont('Regular', 20) self.font = gFont('Regular', 18) self.eventNameFont = gFont('Regular', 18) self.l.setList(list) self.itemHeight = 50 self.rowSplit = 25 self.iconMargin = 4 self.satPosLeft = 160 self.iconWait = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/timer_wait.png')) self.iconWidth = self.iconWait.size().width() self.iconHeight = self.iconWait.size().height() self.iconRecording = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/timer_rec.png')) self.iconPrepared = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/timer_prep.png')) self.iconDone = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/timer_done.png')) self.iconRepeat = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/timer_rep.png')) self.iconZapped = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/timer_zap.png')) self.iconDisabled = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/timer_off.png')) self.iconFailed = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/timer_failed.png')) self.iconAutoTimer = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, 'icons/timer_autotimer.png')) def applySkin(self, desktop, parent): def itemHeight(value): self.itemHeight = int(value) def setServiceNameFont(value): self.serviceNameFont = parseFont(value, ((1, 1), (1, 1))) def setEventNameFont(value): self.eventNameFont = parseFont(value, ((1, 1), (1, 1))) def setFont(value): self.font = parseFont(value, ((1, 1), (1, 1))) def rowSplit(value): self.rowSplit = int(value) def iconMargin(value): self.iconMargin = int(value) def satPosLeft(value): self.satPosLeft = int(value) for attrib, value in list(self.skinAttributes): try: locals().get(attrib)(value) self.skinAttributes.remove((attrib, value)) except: pass self.l.setItemHeight(self.itemHeight) self.l.setFont(0, self.serviceNameFont) self.l.setFont(1, self.font) self.l.setFont(2, self.eventNameFont) return GUIComponent.applySkin(self, desktop, parent) def getCurrent(self): cur = self.l.getCurrentSelection() return cur and cur[0] GUI_WIDGET = eListbox def postWidgetCreate(self, instance): instance.setContent(self.l) self.instance = instance instance.setWrapAround(True) def moveToIndex(self, index): self.instance.moveSelectionTo(index) def getCurrentIndex(self): return self.instance.getCurrentIndex() currentIndex = property(getCurrentIndex, moveToIndex) currentSelection = property(getCurrent) def moveDown(self): self.instance.moveSelection(self.instance.moveDown) def invalidate(self): self.l.invalidate() def entryRemoved(self, idx): self.l.entryRemoved(idx) def getOrbitalPos(self, ref): refstr = None if hasattr(ref, 'sref'): refstr = str(ref.sref) else: refstr = str(ref) refstr = refstr and GetWithAlternative(refstr) if '%3a//' in refstr: return '%s' % _('Stream') else: op = int(refstr.split(':', 10)[6][:-4] or '0', 16) if op == 61166: return '%s' % _('DVB-T') if op == 65535: return '%s' % _('DVB-C') direction = 'E' if op > 1800: op = 3600 - op direction = 'W' return '%d.%d\xc2\xb0%s' % (op // 10, op % 10, direction)
class MovieList(GUIComponent): SORT_ALPHANUMERIC = 1 SORT_RECORDED = 2 SHUFFLE = 3 SORT_ALPHANUMERIC_REVERSE = 4 SORT_RECORDED_REVERSE = 5 SORT_ALPHANUMERIC_FLAT = 6 SORT_ALPHANUMERIC_FLAT_REVERSE = 7 SORT_GROUPWISE = 8 LISTTYPE_ORIGINAL = 1 LISTTYPE_COMPACT_DESCRIPTION = 2 LISTTYPE_COMPACT = 3 LISTTYPE_MINIMAL = 4 HIDE_DESCRIPTION = 1 SHOW_DESCRIPTION = 2 def __init__(self, root, list_type=None, sort_type=None, descr_state=None): GUIComponent.__init__(self) self.list = [] self.list_type = list_type or self.LISTTYPE_MINIMAL self.descr_state = descr_state or self.HIDE_DESCRIPTION self.sort_type = sort_type or self.SORT_GROUPWISE self.firstFileEntry = 0 self.parentDirectory = 0 self.fontName = "Regular" self.fontSizesOriginal = (22, 18, 16) self.fontSizesCompact = (20, 14) self.fontSizesMinimal = (20, 16) self.itemHeights = (75, 37, 25) self.pbarShift = 5 self.pbarHeight = 16 self.pbarLargeWidth = 48 self.partIconeShiftMinimal = 5 self.partIconeShiftCompact = 4 self.partIconeShiftOriginal = 5 self.spaceRight = 2 self.spaceIconeText = 2 self.iconsWidth = 22 self.trashShift = 1 self.dirShift = 1 self.columnsOriginal = (180, 200) self.columnsCompactDescription = (120, 140, 154) self.compactColumn = 200 self.treeDescription = 165 self.reloadDelayTimer = None self.l = eListboxPythonMultiContent() self.tags = set() self.root = None self._playInBackground = None self._char = '' if root is not None: self.reload(root) self.l.setBuildFunc(self.buildMovieListEntry) self.onSelectionChanged = [] self.iconPart = [] for part in range(5): self.iconPart.append( LoadPixmap( resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/part_%d_4.png" % part))) self.iconMovieRec = LoadPixmap( resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/part_new.png")) self.iconMoviePlay = LoadPixmap( resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/movie_play.png")) self.iconMoviePlayRec = LoadPixmap( resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/movie_play_rec.png")) self.iconUnwatched = LoadPixmap( resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/part_unwatched.png")) self.iconFolder = LoadPixmap( resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/folder.png")) self.iconTrash = LoadPixmap( resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/trashcan.png")) self.runningTimers = {} self.updateRecordings() def get_playInBackground(self): return self._playInBackground def set_playInBackground(self, value): if self._playInBackground is not value: index = self.findService(self._playInBackground) if index is not None: self.invalidateItem(index) self.l.invalidateEntry(index) index = self.findService(value) if index is not None: self.invalidateItem(index) self.l.invalidateEntry(index) self._playInBackground = value playInBackground = property(get_playInBackground, set_playInBackground) def updateRecordings(self, timer=None): if timer is not None: if timer.justplay: return result = {} for timer in NavigationInstance.instance.RecordTimer.timer_list: if timer.isRunning() and not timer.justplay: result[os.path.split(timer.Filename)[1] + '.ts'] = timer if self.runningTimers == result: return self.runningTimers = result if timer is not None: if self.reloadDelayTimer is not None: self.reloadDelayTimer.stop() self.reloadDelayTimer = eTimer() self.reloadDelayTimer.callback.append(self.reload) self.reloadDelayTimer.start(5000, 1) def connectSelChanged(self, fnc): if not fnc in self.onSelectionChanged: self.onSelectionChanged.append(fnc) def disconnectSelChanged(self, fnc): if fnc in self.onSelectionChanged: self.onSelectionChanged.remove(fnc) def selectionChanged(self): for x in self.onSelectionChanged: x() def setListType(self, type): if type != self.list_type: self.list_type = type self.redrawList() def setDescriptionState(self, val): self.descr_state = val def setSortType(self, type): self.sort_type = type def applySkin(self, desktop, parent): def warningWrongSkinParameter(string): print "[MovieList] wrong '%s' skin parameters" % string def fontName(value): self.fontName = value def fontSizesOriginal(value): self.fontSizesOriginal = map(int, value.split(",")) if len(self.fontSizesOriginal) != 3: warningWrongSkinParameter(attrib) def fontSizesCompact(value): self.fontSizesCompact = map(int, value.split(",")) if len(self.fontSizesCompact) != 2: warningWrongSkinParameter(attrib) def fontSizesMinimal(value): self.fontSizesMinimal = map(int, value.split(",")) if len(self.fontSizesMinimal) != 2: warningWrongSkinParameter(attrib) def itemHeights(value): self.itemHeights = map(int, value.split(",")) if len(self.itemHeights) != 3: warningWrongSkinParameter(attrib) def pbarShift(value): self.pbarShift = int(value) def pbarHeight(value): self.pbarHeight = int(value) def pbarLargeWidth(value): self.pbarLargeWidth = int(value) def partIconeShiftMinimal(value): self.partIconeShiftMinimal = int(value) def partIconeShiftCompact(value): self.partIconeShiftCompact = int(value) def partIconeShiftOriginal(value): self.partIconeShiftOriginal = int(value) def spaceIconeText(value): self.spaceIconeText = int(value) def iconsWidth(value): self.iconsWidth = int(value) def trashShift(value): self.trashShift = int(value) def dirShift(value): self.dirShift = int(value) def spaceRight(value): self.spaceRight = int(value) def columnsOriginal(value): self.columnsOriginal = map(int, value.split(",")) if len(self.columnsOriginal) != 2: warningWrongSkinParameter(attrib) def columnsCompactDescription(value): self.columnsCompactDescription = map(int, value.split(",")) if len(self.columnsCompactDescription) != 3: warningWrongSkinParameter(attrib) def compactColumn(value): self.compactColumn = int(value) def treeDescription(value): self.treeDescription = int(value) for (attrib, value) in self.skinAttributes[:]: try: locals().get(attrib)(value) self.skinAttributes.remove((attrib, value)) except: pass self.redrawList() return GUIComponent.applySkin(self, desktop, parent) def redrawList(self): if self.list_type == MovieList.LISTTYPE_ORIGINAL: for i in range(3): self.l.setFont(i, gFont(self.fontName, self.fontSizesOriginal[i])) self.itemHeight = self.itemHeights[0] elif self.list_type == MovieList.LISTTYPE_COMPACT_DESCRIPTION or self.list_type == MovieList.LISTTYPE_COMPACT: for i in range(2): self.l.setFont(i, gFont(self.fontName, self.fontSizesCompact[i])) self.itemHeight = self.itemHeights[1] else: for i in range(2): self.l.setFont(i, gFont(self.fontName, self.fontSizesMinimal[i])) self.itemHeight = self.itemHeights[2] self.l.setItemHeight(self.itemHeight) def invalidateItem(self, index): x = self.list[index] self.list[index] = (x[0], x[1], x[2], None) def invalidateCurrentItem(self): self.invalidateItem(self.getCurrentIndex()) def buildMovieListEntry(self, serviceref, info, begin, data): width = self.l.getItemSize().width() iconSize = self.iconsWidth space = self.spaceIconeText r = self.spaceRight pathName = serviceref.getPath() res = [None] if serviceref.flags & eServiceReference.mustDescent: # Directory # Name is full path name valign_center = 0 if self.list_type == MovieList.LISTTYPE_MINIMAL: valign_center = RT_VALIGN_CENTER x = iconSize + space tn = self.treeDescription if info is None: # Special case: "parent" txt = ".." else: p = os.path.split(pathName) if not p[1]: # if path ends in '/', p is blank. p = os.path.split(p[0]) txt = p[1] if txt == ".Trash": res.append( MultiContentEntryPixmapAlphaTest( pos=(0, self.trashShift), size=(iconSize, self.iconTrash.size().height()), png=self.iconTrash)) res.append( MultiContentEntryText( pos=(x, 0), size=(width - x - tn - r, self.itemHeight), font=0, flags=RT_HALIGN_LEFT | valign_center, text=_("Deleted items"))) res.append( MultiContentEntryText(pos=(width - tn - r, 0), size=(tn, self.itemHeight), font=1, flags=RT_HALIGN_RIGHT | valign_center, text=_("Trash can"))) return res res.append( MultiContentEntryPixmapAlphaTest(pos=(0, self.dirShift), size=(iconSize, iconSize), png=self.iconFolder)) res.append( MultiContentEntryText(pos=(x, 0), size=(width - x - tn - r, self.itemHeight), font=0, flags=RT_HALIGN_LEFT | valign_center, text=txt)) res.append( MultiContentEntryText(pos=(width - tn - r, 0), size=(tn, self.itemHeight), font=1, flags=RT_HALIGN_RIGHT | valign_center, text=_("Directory"))) return res if (data == -1) or (data is None): data = MovieListData() cur_idx = self.l.getCurrentSelectionIndex() x = self.list[cur_idx] # x = ref,info,begin,... if config.usage.load_length_of_movies_in_moviellist.value: data.len = x[1].getLength(x[0]) #recalc the movie length... else: data.len = 0 #dont recalc movielist to speedup loading the list self.list[cur_idx] = ( x[0], x[1], x[2], data ) #update entry in list... so next time we don't need to recalc data.txt = info.getName(serviceref) if config.movielist.hide_extensions.value: fileName, fileExtension = os.path.splitext(data.txt) if fileExtension in KNOWN_EXTENSIONS: data.txt = fileName data.icon = None data.part = None if os.path.split(pathName)[1] in self.runningTimers: if self.playInBackground and serviceref == self.playInBackground: data.icon = self.iconMoviePlayRec else: data.icon = self.iconMovieRec elif self.playInBackground and serviceref == self.playInBackground: data.icon = self.iconMoviePlay else: switch = config.usage.show_icons_in_movielist.value data.part = moviePlayState(pathName + '.cuts', serviceref, data.len) if switch == 'i': if data.part is None: if config.usage.movielist_unseen.value: data.icon = self.iconUnwatched else: data.icon = self.iconPart[data.part // 25] elif switch == 'p' or switch == 's': if data.part is None: if config.usage.movielist_unseen.value: data.part = 0 data.partcol = 0x808080 else: data.partcol = 0xf0f0f0 service = ServiceReference( info.getInfoString(serviceref, iServiceInformation.sServiceref)) if service is None: data.serviceName = None else: data.serviceName = service.getServiceName() data.description = info.getInfoString( serviceref, iServiceInformation.sDescription) len = data.len if len > 0: len = "%d:%02d" % (len / 60, len % 60) else: len = "" if data.icon is not None: if self.list_type in (MovieList.LISTTYPE_COMPACT_DESCRIPTION, MovieList.LISTTYPE_COMPACT): pos = (0, self.partIconeShiftCompact) elif self.list_type == MovieList.LISTTYPE_ORIGINAL: pos = (0, self.partIconeShiftOriginal) else: pos = (0, self.partIconeShiftMinimal) res.append( MultiContentEntryPixmapAlphaTest( pos=pos, size=(iconSize, data.icon.size().height()), png=data.icon)) switch = config.usage.show_icons_in_movielist.value if switch in ('p', 's'): if switch == 'p': iconSize = self.pbarLargeWidth if data.part is not None: res.append( MultiContentEntryProgress(pos=(0, self.pbarShift), size=(iconSize, self.pbarHeight), percent=data.part, borderWidth=2, foreColor=data.partcol, foreColorSelected=None, backColor=None, backColorSelected=None)) elif switch == 'i': pass else: iconSize = 0 begin_string = "" if begin > 0: begin_string = ', '.join(FuzzyTime(begin, inPast=True)) ih = self.itemHeight if self.list_type == MovieList.LISTTYPE_ORIGINAL: fc, sc = self.columnsOriginal[0], self.columnsOriginal[1] ih1 = (ih * 2) / 5 # 75 -> 30 ih2 = (ih * 2) / 3 # 75 -> 50 res.append( MultiContentEntryText(pos=(iconSize + space, 0), size=(width - fc - r, ih1), font=0, flags=RT_HALIGN_LEFT, text=data.txt)) if self.tags: res.append( MultiContentEntryText(pos=(width - fc - r, 0), size=(fc, ih1), font=2, flags=RT_HALIGN_RIGHT, text=info.getInfoString( serviceref, iServiceInformation.sTags))) if data.serviceName: res.append( MultiContentEntryText(pos=(sc - r, ih2), size=(sc, ih2 - ih1), font=1, flags=RT_HALIGN_LEFT, text=data.serviceName)) else: if data.serviceName: res.append( MultiContentEntryText(pos=(width - fc - r, 0), size=(fc, ih1), font=2, flags=RT_HALIGN_RIGHT, text=data.serviceName)) res.append( MultiContentEntryText(pos=(0, ih1), size=(width - r, ih2 - ih1), font=1, flags=RT_HALIGN_LEFT, text=data.description)) res.append( MultiContentEntryText(pos=(0, ih2), size=(sc - r, ih - ih2), font=1, flags=RT_HALIGN_LEFT, text=begin_string)) if len: res.append( MultiContentEntryText(pos=(width - sc - r, ih2), size=(sc, ih - ih2), font=1, flags=RT_HALIGN_RIGHT, text=len)) elif self.list_type == MovieList.LISTTYPE_COMPACT_DESCRIPTION: ih1 = ((ih * 8) + 14) / 15 # 37 -> 20, round up if len: lenSize = 58 * ih / 37 else: lenSize = 0 fc, sc, tc = self.columnsCompactDescription[ 0], self.columnsCompactDescription[ 1], self.columnsCompactDescription[2] res.append( MultiContentEntryText(pos=(iconSize + space, 0), size=(width - sc - r, ih1), font=0, flags=RT_HALIGN_LEFT, text=data.txt)) res.append( MultiContentEntryText(pos=(0, ih1), size=(width - tc - lenSize - r, ih - ih1), font=1, flags=RT_HALIGN_LEFT, text=data.description)) res.append( MultiContentEntryText(pos=(width - fc - r, 6), size=(fc, ih1), font=1, flags=RT_HALIGN_RIGHT, text=begin_string)) if data.serviceName: res.append( MultiContentEntryText(pos=(width - tc - lenSize - r, ih1), size=(tc, ih - ih1), font=1, flags=RT_HALIGN_RIGHT, text=data.serviceName)) if lenSize: res.append( MultiContentEntryText(pos=(width - lenSize - r, ih1), size=(lenSize, ih - ih1), font=1, flags=RT_HALIGN_RIGHT, text=len)) elif self.list_type == MovieList.LISTTYPE_COMPACT: col = self.compactColumn ih1 = ((ih * 8) + 14) / 15 # 37 -> 20, round up if len: lenSize = 2 * ih else: lenSize = 0 res.append( MultiContentEntryText(pos=(iconSize + space, 0), size=(width - lenSize - iconSize - space - r, ih1), font=0, flags=RT_HALIGN_LEFT, text=data.txt)) if self.tags: res.append( MultiContentEntryText(pos=(width - col - r, ih1), size=(col, ih - ih1), font=1, flags=RT_HALIGN_RIGHT, text=info.getInfoString( serviceref, iServiceInformation.sTags))) if data.serviceName: res.append( MultiContentEntryText(pos=(col, ih1), size=(col, ih - ih1), font=1, flags=RT_HALIGN_LEFT, text=data.serviceName)) else: if data.serviceName: res.append( MultiContentEntryText(pos=(width - col - r, ih1), size=(col, ih - ih1), font=1, flags=RT_HALIGN_RIGHT, text=data.serviceName)) res.append( MultiContentEntryText(pos=(0, ih1), size=(col, ih - ih1), font=1, flags=RT_HALIGN_LEFT, text=begin_string)) if lenSize: res.append( MultiContentEntryText(pos=(width - lenSize - r, 0), size=(lenSize, ih1), font=0, flags=RT_HALIGN_RIGHT, text=len)) else: if (self.descr_state == MovieList.SHOW_DESCRIPTION) or not len: dateSize = ih * 145 / 25 # 25 -> 145 res.append( MultiContentEntryText( pos=(iconSize + space, 0), size=(width - iconSize - space - dateSize - r, ih), font=0, flags=RT_HALIGN_LEFT | RT_VALIGN_CENTER, text=data.txt)) res.append( MultiContentEntryText(pos=(width - dateSize - r, 4), size=(dateSize, ih), font=1, flags=RT_HALIGN_RIGHT | RT_VALIGN_CENTER, text=begin_string)) else: lenSize = ih * 3 # 25 -> 75 res.append( MultiContentEntryText(pos=(iconSize + space, 0), size=(width - lenSize - iconSize - space - r, ih), font=0, flags=RT_HALIGN_LEFT, text=data.txt)) res.append( MultiContentEntryText(pos=(width - lenSize - r, 0), size=(lenSize, ih), font=0, flags=RT_HALIGN_RIGHT, text=len)) return res def moveToFirstMovie(self): if self.firstFileEntry < len(self.list): self.instance.moveSelectionTo(self.firstFileEntry) else: # there are no movies, just directories... self.moveToFirst() def moveToParentDirectory(self): if self.parentDirectory < len(self.list): self.instance.moveSelectionTo(self.parentDirectory) else: self.moveToFirst() def moveToLast(self): if self.list: self.instance.moveSelectionTo(len(self.list) - 1) def moveToFirst(self): if self.list: self.instance.moveSelectionTo(0) def moveToIndex(self, index): self.instance.moveSelectionTo(index) def getCurrentIndex(self): return self.instance.getCurrentIndex() def getCurrentEvent(self): l = self.l.getCurrentSelection() return l and l[0] and l[1] and l[1].getEvent(l[0]) def getCurrent(self): l = self.l.getCurrentSelection() return l and l[0] def getItem(self, index): if self.list: if len(self.list) > index: return self.list[index] and self.list[index][0] GUI_WIDGET = eListbox def postWidgetCreate(self, instance): instance.setContent(self.l) instance.selectionChanged.get().append(self.selectionChanged) def preWidgetRemove(self, instance): instance.setContent(None) instance.selectionChanged.get().remove(self.selectionChanged) def reload(self, root=None, filter_tags=None): if self.reloadDelayTimer is not None: self.reloadDelayTimer.stop() self.reloadDelayTimer = None if root is not None: self.load(root, filter_tags) else: self.load(self.root, filter_tags) self.l.setList(self.list) def removeService(self, service): index = self.findService(service) if index is not None: del self.list[index] self.l.setList(self.list) def findService(self, service): if service is None: return None for index, l in enumerate(self.list): if l[0] == service: return index return None def __len__(self): return len(self.list) def __getitem__(self, index): return self.list[index] def __iter__(self): return self.list.__iter__() def load(self, root, filter_tags): # this lists our root service, then building a # nice list del self.list[:] serviceHandler = eServiceCenter.getInstance() numberOfDirs = 0 reflist = root and serviceHandler.list(root) if reflist is None: print "listing of movies failed" return realtags = set() autotags = {} rootPath = os.path.normpath(root.getPath()) parent = None # Don't navigate above the "root" if len(rootPath) > 1 and (os.path.realpath(rootPath) != os.path.realpath( config.movielist.root.value)): parent = os.path.split(os.path.normpath(rootPath))[0] if parent and (parent not in defaultInhibitDirs): # enigma wants an extra '/' appended if not parent.endswith('/'): parent += '/' ref = eServiceReference("2:0:1:0:0:0:0:0:0:0:" + parent) ref.flags = eServiceReference.flagDirectory self.list.append((ref, None, 0, -1)) numberOfDirs += 1 while 1: serviceref = reflist.getNext() if not serviceref.valid(): break if config.ParentalControl.servicepinactive.value and config.ParentalControl.storeservicepin.value != "never": from Components.ParentalControl import parentalControl if not parentalControl.sessionPinCached and parentalControl.isProtected( serviceref): continue info = serviceHandler.info(serviceref) if info is None: info = justStubInfo begin = info.getInfo(serviceref, iServiceInformation.sTimeCreate) if serviceref.flags & eServiceReference.mustDescent: self.list.append((serviceref, info, begin, -1)) numberOfDirs += 1 continue # convert separe-separated list of tags into a set this_tags = info.getInfoString( serviceref, iServiceInformation.sTags).split(' ') name = info.getName(serviceref) if this_tags == ['']: # No tags? Auto tag! this_tags = name.replace(',', ' ').replace('.', ' ').split() # For auto tags, we are keeping a (tag, movies) dictionary. #It will be used later to check if movies have a complete sentence in common. for tag in this_tags: if tag in autotags: autotags[tag].append(name) else: autotags[tag] = [name] else: realtags.update(this_tags) # filter_tags is either None (which means no filter at all), or # a set. In this case, all elements of filter_tags must be present, # otherwise the entry will be dropped. if filter_tags is not None: this_tags = set(this_tags) if not this_tags.issuperset(filter_tags): print "Skipping", name, "tags=", this_tags, " filter=", filter_tags continue self.list.append((serviceref, info, begin, -1)) self.firstFileEntry = numberOfDirs self.parentDirectory = 0 if self.sort_type == MovieList.SORT_ALPHANUMERIC: self.list.sort(key=self.buildAlphaNumericSortKey) elif self.sort_type == MovieList.SORT_ALPHANUMERIC_FLAT: self.list.sort(key=self.buildAlphaNumericFlatSortKey) elif self.sort_type == MovieList.SORT_ALPHANUMERIC_FLAT_REVERSE: self.list.sort(key=self.buildAlphaNumericFlatSortKey, reverse=True) elif self.sort_type == MovieList.SORT_RECORDED: self.list.sort(key=self.buildBeginTimeSortKey) else: #always sort first this way to avoid shuffle and reverse-sort directories self.list.sort(key=self.buildGroupwiseSortkey) if self.sort_type == MovieList.SHUFFLE: dirlist = self.list[:numberOfDirs] shufflelist = self.list[numberOfDirs:] random.shuffle(shufflelist) self.list = dirlist + shufflelist elif self.sort_type == MovieList.SORT_ALPHANUMERIC_REVERSE: self.list = self.list[:numberOfDirs] + sorted( self.list[numberOfDirs:], key=self.buildAlphaNumericSortKey, reverse=True) elif self.sort_type == MovieList.SORT_RECORDED_REVERSE: self.list = self.list[:numberOfDirs] + sorted( self.list[numberOfDirs:], key=self.buildBeginTimeSortKey, reverse=True) if self.root and numberOfDirs > 0: rootPath = os.path.normpath(self.root.getPath()) if not rootPath.endswith('/'): rootPath += '/' if rootPath != parent: # with new sort types directories may be in between files, so scan whole # list for parentDirectory index. Usually it is the first one anyway for index, item in enumerate(self.list): if item[0].flags & eServiceReference.mustDescent: itempath = os.path.normpath(item[0].getPath()) if not itempath.endswith('/'): itempath += '/' if itempath == rootPath: self.parentDirectory = index break self.root = root # finally, store a list of all tags which were found. these can be presented # to the user to filter the list # ML: Only use the tags that occur more than once in the list OR that were # really in the tag set of some file. # reverse the dictionary to see which unique movie each tag now references rautotags = {} for tag, movies in autotags.items(): if (len(movies) > 1): movies = tuple(movies) # a tuple can be hashed, but a list not item = rautotags.get(movies, []) if not item: rautotags[movies] = item item.append(tag) self.tags = {} for movies, tags in rautotags.items(): movie = movies[0] # format the tag lists so that they are in 'original' order tags.sort(key=movie.find) first = movie.find(tags[0]) last = movie.find(tags[-1]) + len(tags[-1]) match = movie start = 0 end = len(movie) # Check if the set has a complete sentence in common, and how far for m in movies[1:]: if m[start:end] != match: if not m.startswith(movie[:last]): start = first if not m.endswith(movie[first:]): end = last match = movie[start:end] if m[start:end] != match: match = '' break # Adding the longest common sentence to the tag list if match: self.tags[match] = set(tags) else: match = ' '.join(tags) if (len(match) > 2) or ( match in realtags): #Omit small words, only for auto tags self.tags[match] = set(tags) # Adding the realtags to the tag list for tag in realtags: self.tags[tag] = set([tag]) def buildAlphaNumericSortKey(self, x): # x = ref,info,begin,... ref = x[0] name = x[1] and x[1].getName(ref) if ref.flags & eServiceReference.mustDescent: return (0, name and name.lower() or "", -x[2]) return (1, name and name.lower() or "", -x[2]) def buildAlphaNumericFlatSortKey(self, x): # x = ref,info,begin,... ref = x[0] name = x[1] and x[1].getName(ref) if name and ref.flags & eServiceReference.mustDescent: # only use directory basename for sorting p = os.path.split(name) if not p[1]: # if path ends in '/', p is blank. p = os.path.split(p[0]) name = p[1] # print "Sorting for -%s-" % name return (1, name and name.lower() or "", -x[2]) def buildBeginTimeSortKey(self, x): ref = x[0] if ref.flags & eServiceReference.mustDescent: return (0, x[1] and x[1].getName(ref).lower() or "") return (1, -x[2]) def buildGroupwiseSortkey(self, x): # Sort recordings by date, sort MP3 and stuff by name ref = x[0] if ref.type >= eServiceReference.idUser: return self.buildAlphaNumericSortKey(x) else: return self.buildBeginTimeSortKey(x) def moveTo(self, serviceref): index = self.findService(serviceref) if index is not None: self.instance.moveSelectionTo(index) return True return False def moveDown(self): self.instance.moveSelection(self.instance.moveDown) def moveUp(self): self.instance.moveSelection(self.instance.moveUp) def moveToChar(self, char, lbl=None): self._char = char self._lbl = lbl if lbl: lbl.setText(self._char) lbl.visible = True self.moveToCharTimer = eTimer() self.moveToCharTimer.callback.append(self._moveToChrStr) self.moveToCharTimer.start( 1000, True ) #time to wait for next key press to decide which letter to use... def moveToString(self, char, lbl=None): self._char = self._char + char.upper() self._lbl = lbl if lbl: lbl.setText(self._char) lbl.visible = True self.moveToCharTimer = eTimer() self.moveToCharTimer.callback.append(self._moveToChrStr) self.moveToCharTimer.start( 1000, True ) #time to wait for next key press to decide which letter to use... def _moveToChrStr(self): currentIndex = self.instance.getCurrentIndex() found = False if currentIndex < (len(self.list) - 1): itemsBelow = self.list[currentIndex + 1:] #first search the items below the selection for index, item in enumerate(itemsBelow): ref = item[0] itemName = getShortName(item[1].getName(ref).upper(), ref) if len(self._char) == 1 and itemName.startswith(self._char): found = True self.instance.moveSelectionTo(index + currentIndex + 1) break elif len(self._char) > 1 and itemName.find(self._char) >= 0: found = True self.instance.moveSelectionTo(index + currentIndex + 1) break if found == False and currentIndex > 0: itemsAbove = self.list[ 1: currentIndex] #first item (0) points parent folder - no point to include for index, item in enumerate(itemsAbove): ref = item[0] itemName = getShortName(item[1].getName(ref).upper(), ref) if len(self._char) == 1 and itemName.startswith(self._char): found = True self.instance.moveSelectionTo(index + 1) break elif len(self._char) > 1 and itemName.find(self._char) >= 0: found = True self.instance.moveSelectionTo(index + 1) break self._char = '' if self._lbl: self._lbl.visible = False
class ServiceList(HTMLComponent, GUIComponent): MODE_NORMAL = 0 MODE_FAVOURITES = 1 KEY_BEGIN_MARGIN = "beginMargin" KEY_END_MARGIN = "endMargin" KEY_PICON_WIDTH = "piconWidth" KEY_PICON_WIDTH_BIG = "piconWidthBig" KEY_PICON_OFFSET = "piconOffset" KEY_PROGRESS_BAR_WIDTH = "progressBarWidth" KEY_PROGRESS_BAR_MARGIN = "progressBarMargin" KEY_PROGRESS_BAR_HEIGHT = "progressBarHeight" KEY_SERVICE_INFO_HEIGHT_ADD ="serviceInfoHeightAdd" KEY_SERVICE_ITEM_HEIGHT = "serviceItemHeight" KEY_SERVICE_ITEM_HEIGHT_LARGE ="serviceItemHeightLarge" KEY_SERVICE_NUMBER_WIDTH = "serviceNumberWidth" KEY_TEXT_OFFSET = "textOffset" def getDesktopWith(self): return getDesktop(0).size().width() def __init__(self, session = None): GUIComponent.__init__(self) self._componentSizes = componentSizes[componentSizes.SERVICE_LIST] Log.i(self._componentSizes) tlf = TemplatedListFonts() upper_service_name_limit = self.getDesktopWith() / 3 config.usage.configselection_servicenamecolwidth.limits = [(100, upper_service_name_limit),] self.session = session self.mode = self.MODE_NORMAL self.picFolder = LoadPixmap(cached=True, path=resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/folder.png")) self.picMarker = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "skin_default/icons/marker.png")) self.picDVB_S = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "ico_dvb_s-fs8.png")) self.picDVB_C = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "ico_dvb_c-fs8.png")) self.picDVB_T = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "ico_dvb_t-fs8.png")) self.picServiceGroup = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, "ico_service_group-fs8.png")) self.markedForeground = 0xffffff self.markedBackground = 0xff0000 self.markedForegroundSelected = 0xffffff self.markedBackgroundSelected = 0x800000 colors = TemplatedColors().colors if "ListboxMarkedForeground" in colors: self.markedForeground = colors["ListboxMarkedForeground"] if "ListboxMarkedBackground" in colors: self.markedBackground = colors["ListboxMarkedBackground"] if "ListboxMarkedAndSelectedForeground" in colors: self.markedForegroundSelected = colors["ListboxMarkedAndSelectedForeground"] if "ListboxMarkedAndSelectedBackground" in colors: self.markedBackgroundSelected = colors["ListboxMarkedAndSelectedBackground"] self.serviceNotAvail = 0xbbbbbb self.serviceEventProgressbarColor = None self.serviceEventProgressbarColorSelected = None self.serviceEventProgressbarBackColor = None self.serviceEventProgressbarBackColorSelected = None self.serviceEventProgressbarBorderColor = None self.serviceEventProgressbarBorderColorSelected = None self.serviceDescriptionColor = 0xe7b53f self.serviceDescriptionColorSelected = 0xe7b53f self.recordingColor = 0xff4A3C self.recordingColorSelected = 0xff4A3C self.additionalInfoColor = None self.additionalInfoColorSelected = None self.picServiceEventProgressbar = None self.selectionPixmapStandard = None self.selectionPixmapBig = None self.l = eListboxServiceContent() self.l.setBuildFunc(self.buildOptionEntry, True) self.l.setFont(0, gFont(tlf.face(TemplatedListFonts.SMALL), tlf.size(TemplatedListFonts.SMALL))) # AdditionalInfoFont self.l.setFont(1, gFont(tlf.face(TemplatedListFonts.MEDIUM), tlf.size(TemplatedListFonts.MEDIUM))) # ServiceNumberFont self.l.setFont(2, gFont(tlf.face(TemplatedListFonts.BIG), tlf.size(TemplatedListFonts.BIG))) # ServiceNameFont self.l.setFont(3, gFont(tlf.face(TemplatedListFonts.SMALL), tlf.size(TemplatedListFonts.SMALL))) # ServiceInfoFont self.serviceNameFont = gFont(tlf.face(TemplatedListFonts.BIG), tlf.size(TemplatedListFonts.BIG)) self.serviceInfoFontHeight = tlf.size(TemplatedListFonts.SMALL) self.serviceInfoHeight = self.serviceInfoFontHeight + self._componentSizes.get(self.KEY_SERVICE_INFO_HEIGHT_ADD, 6) self.additionalInfoFont = gFont(tlf.face(TemplatedListFonts.SMALL), tlf.size(TemplatedListFonts.SMALL)) self.list = [] self.size = 0 self.service_center = eServiceCenter.getInstance() self.numberoffset = 0 self.is_playable_ignore = eServiceReference() self.root = None self.itemHeight = self._componentSizes.get(self.KEY_SERVICE_ITEM_HEIGHT, 28) self.itemHeightHigh = self._componentSizes.get(self.KEY_SERVICE_ITEM_HEIGHT_LARGE, 60) self.l.setItemHeight(self.itemHeight) self.onSelectionChanged = [ ] self.recordingList = {} self.piconLoader = PiconLoader() if self.session: self.session.nav.RecordTimer.on_state_change.append(self.onTimerEntryStateChange) config.usage.configselection_showrecordings.addNotifier(self.getRecordingList, initial_call = True) config.usage.configselection_bigpicons.addNotifier(self.setItemHeight, initial_call = True) config.usage.configselection_secondlineinfo.addNotifier(self.setItemHeight, initial_call = False) self._reloadTimer = eTimer() self.__reloadTimerConn = self._reloadTimer.timeout.connect(self._reload) def onShow(self): GUIComponent.onShow(self) self._resetTimer() def onHide(self): GUIComponent.onHide(self) self._reloadTimer.stop() def _reload(self): self.l.refresh() self._resetTimer() def _resetTimer(self): secs = 60 - datetime.now().second #next full minute self._reloadTimer.startLongTimer(secs) def getRecordingList(self,configElement = None): self.recordingList = {} if config.usage.configselection_showrecordings.value: if NavigationInstance.instance.getRecordings(): for timer in NavigationInstance.instance.RecordTimer.timer_list: if timer.state == TimerEntry.StateRunning and not timer.justplay and hasattr(timer, "Filename"): self.recordingList[str(timer.service_ref)] = 1 def onTimerEntryStateChange(self,timer): if config.usage.configselection_showrecordings.value: if hasattr(timer, "Filename") and not timer.justplay and timer.state == TimerEntry.StateRunning: self.recordingList[str(timer.service_ref)] = 1 else: if self.recordingList.has_key(str(timer.service_ref)): del self.recordingList[str(timer.service_ref)] def setItemHeight(self, configElement = None): if (config.usage.configselection_bigpicons.value or config.usage.configselection_secondlineinfo.value != "0") and self.mode == self.MODE_FAVOURITES: self.l.setItemHeight(self.itemHeightHigh) if self.instance is not None and self.selectionPixmapBig: self.instance.setSelectionPicture(self.selectionPixmapBig) else: self.l.setItemHeight(self.itemHeight) if self.instance is not None and self.selectionPixmapStandard: self.instance.setSelectionPicture(self.selectionPixmapStandard) def _buildOptionEntryProgressBar(self, event, xoffset, width, height): percent = 0 progressW = self._progressBarWidth() progressH = self._componentSizes.get(self.KEY_PROGRESS_BAR_HEIGHT, 8) if event and event.getDuration(): now = int(time()) percent = 100 * (now - event.getBeginTime()) / event.getDuration() top = int((height - progressH) / 2) if self.picServiceEventProgressbar is None: return(eListboxPythonMultiContent.TYPE_PROGRESS, xoffset, top, progressW, progressH, percent, 1, self.serviceEventProgressbarColor, self.serviceEventProgressbarColorSelected, self.serviceEventProgressbarBackColor, self.serviceEventProgressbarBackColorSelected) else: return(eListboxPythonMultiContent.TYPE_PROGRESS_PIXMAP, xoffset, top, progressW, progressH, percent, self.picServiceEventProgressbar, 1, self.serviceEventProgressbarBorderColor, self.serviceEventProgressbarBorderColorSelected, self.serviceEventProgressbarBackColor, self.serviceEventProgressbarBackColorSelected) def _progressBarWidth(self, withOffset=False, withProgressBarSize=True): width = 0 if withProgressBarSize: width += self._componentSizes.get(self.KEY_PROGRESS_BAR_WIDTH, 52) if withOffset: width += self._componentSizes.get(self.KEY_PROGRESS_BAR_MARGIN, 8) return width def _calcTextWidth(self, text, font=None, size=None): if size: self.textRenderer.resize(size) if font: self.textRenderer.setFont(font) self.textRenderer.setText(text) return self.textRenderer.calculateSize().width() def _buildOptionEntryServicePixmap(self, service): pixmap = None if service.flags & eServiceReference.isMarker: pixmap = self.picMarker elif service.flags & eServiceReference.isGroup: pixmap = self.picServiceGroup elif service.flags & eServiceReference.isDirectory: pixmap = self.picFolder else: orbpos = service.getUnsignedData(4) >> 16; if orbpos == 0xFFFF: pixmap = self.picDVB_C elif orbpos == 0xEEEE: pixmap = self.picDVB_T else: pixmap = self.picDVB_S return pixmap def _buildOptionEntryAddTimeDisplay(self, event, isPlayable, columnStyle): addtimedisplay = "" addtimedisplayWidth = 0 if not ( config.usage.configselection_showadditionaltimedisplay.value != "0" and event and isPlayable ): return addtimedisplay, addtimedisplayWidth textTpl = "" maxTimeValue = 9999 if config.usage.configselection_showadditionaltimedisplay.value == "1": # percent now = int(time()) percent = 100 * (now - event.getBeginTime()) / event.getDuration() addtimedisplay = "%d%%" % percent textTpl = "100%" elif config.usage.configselection_showadditionaltimedisplay.value == "2": # remain now = int(time()) remain = int((event.getBeginTime() + event.getDuration() - now) / 60) addtimedisplay = "+%d min" %(remain,) textTpl = "+%d min" %(maxTimeValue,) elif config.usage.configselection_showadditionaltimedisplay.value == "3": # Remain / duration now = int(time()) remain = int((event.getBeginTime() + event.getDuration() - now) / 60) duration = int(event.getDuration() / 60) addtimedisplay = "+%d/%d min" % (remain, duration) textTpl = "+%d/%d min" % (maxTimeValue, maxTimeValue) elif config.usage.configselection_showadditionaltimedisplay.value == "4": # elapsed now = int(time()) elapsed = int((now - event.getBeginTime()) / 60) addtimedisplay = "%d min" % (elapsed,) textTpl = "%d min" % (maxTimeValue,) elif config.usage.configselection_showadditionaltimedisplay.value == "5": # elapsed / duration now = int(time()) elapsed = int((now - event.getBeginTime()) / 60) duration = int(event.getDuration() / 60) addtimedisplay = "%d/%d min" % (elapsed, duration) textTpl = "%d/%d min" % (maxTimeValue, maxTimeValue) elif config.usage.configselection_showadditionaltimedisplay.value == "6": # elapsed / remain / duration now = int(time()) elapsed = int((now - event.getBeginTime()) / 60) remain = int((event.getBeginTime() + event.getDuration() - now) / 60) duration = int(event.getDuration() / 60) addtimedisplay = "%d/+%d/%d min" % (elapsed, remain, duration) textTpl = "%d/+%d/%d mwidthin" % (maxTimeValue, maxTimeValue, maxTimeValue) elif config.usage.configselection_showadditionaltimedisplay.value == "7": # begin - end time beginTime = localtime(event.getBeginTime()) endTime = localtime(event.getBeginTime()+event.getDuration()) addtimedisplay = "%02d:%02d - %02d:%02d" % (beginTime[3],beginTime[4],endTime[3],endTime[4]) textTpl = "00:00 - 00:000" if columnStyle: addtimedisplayWidth = self._calcTextWidth(textTpl, font=self.additionalInfoFont, size=eSize(self.getDesktopWith() / 3, 0)) return addtimedisplay, addtimedisplayWidth def _buildOptionEntryServicePicon(self, service): if service.flags & eServiceReference.mustDescent: alist = ServiceReference(service).list() first_in_alternative = alist and alist.getNext() if first_in_alternative: service_str = first_in_alternative.toString() else: service_str = service.toString() else: service_str = service.toString() return self.piconLoader.getPicon(service_str) def _checkHasRecording(self, service, isPlayable): if not config.usage.configselection_showrecordings.value: return False if self.recordingList.has_key(service.toString()): return True if isPlayable and len(self.recordingList) and service.flags & eServiceReference.mustDescent: alist = ServiceReference(service).list() while True: aservice = alist.getNext() if not aservice.valid(): break if self.recordingList.has_key(aservice.toString()): return True return False def buildOptionEntry(self, service, **args): width = self.l.getItemSize().width() width -= self._componentSizes.get(self.KEY_END_MARGIN, 5) height = self.l.getItemSize().height() selected = args["selected"] res = [ None ] showListNumbers = config.usage.configselection_showlistnumbers.value showPicons = self.mode == self.MODE_FAVOURITES and config.usage.configselection_showpicons.value showServiceName = self.mode == self.MODE_NORMAL or (self.mode == self.MODE_FAVOURITES and config.usage.configselection_showservicename.value) showProgressbar = config.usage.show_event_progress_in_servicelist.value progressbarPosition = config.usage.configselection_progressbarposition.value servicenameWidth = config.usage.configselection_servicenamecolwidth.value columnStyle = config.usage.configselection_columnstyle.value additionalposition = config.usage.configselection_additionaltimedisplayposition.value bigPicons = self.mode == self.MODE_FAVOURITES and config.usage.configselection_bigpicons.value secondlineinfo = config.usage.configselection_secondlineinfo.value # get service information service_info = self.service_center.info(service) isMarker = service.flags & eServiceReference.isMarker isPlayable = not(service.flags & eServiceReference.isDirectory or isMarker) recording = self._checkHasRecording(service, isPlayable) marked = 0 if self.l.isCurrentMarked() and selected: marked = 2 elif self.l.isMarked(service): if selected: marked = 2 else: marked = 1 if marked == 1: # marked additionalInfoColor = serviceDescriptionColor = forgroundColor = self.markedForeground backgroundColor = self.markedBackground forgroundColorSel = backgroundColorSel = additionalInfoColorSelected = serviceDescriptionColorSelected = None elif marked == 2: # marked and selected additionalInfoColorSelected = serviceDescriptionColorSelected = forgroundColorSel = self.markedForegroundSelected backgroundColorSel = self.markedBackgroundSelected forgroundColor = additionalInfoColor = serviceDescriptionColor = backgroundColor = None else: if recording: forgroundColor = additionalInfoColor = serviceDescriptionColor = self.recordingColor forgroundColorSel = additionalInfoColorSelected = serviceDescriptionColorSelected = self.recordingColorSelected backgroundColor = backgroundColorSel = None else: forgroundColor = forgroundColorSel = backgroundColor = backgroundColorSel = None serviceDescriptionColor = self.serviceDescriptionColor serviceDescriptionColorSelected = self.serviceDescriptionColorSelected additionalInfoColor = self.additionalInfoColor additionalInfoColorSelected = self.additionalInfoColorSelected if (marked == 0 and isPlayable and service_info and not service_info.isPlayable(service, self.is_playable_ignore)): forgroundColor = forgroundColorSel = additionalInfoColor = additionalInfoColorSelected = serviceDescriptionColor = serviceDescriptionColorSelected = self.serviceNotAvail # set windowstyle if marked > 0: res.append((eListboxPythonMultiContent.TYPE_TEXT, 0, 0, width , height, 1, RT_HALIGN_RIGHT, "", forgroundColor, forgroundColorSel, backgroundColor, backgroundColorSel)) info = self.service_center.info(service) serviceName = info and info.getName(service) or "<n/a>" event = info and info.getEvent(service) index = self.getCurrentIndex() xoffset = self._componentSizes.get(self.KEY_BEGIN_MARGIN, 5) pixmap = self._buildOptionEntryServicePixmap(service) drawProgressbar = isPlayable and showProgressbar progressBarWidth = self._progressBarWidth(withOffset=True) textOffset = self._componentSizes.get(self.KEY_TEXT_OFFSET, 10) if pixmap is not None: pixmap_size = self.picMarker.size() pix_width = pixmap_size.width() pix_height = pixmap_size.height() ypos = (height - pix_height) / 2 res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, xoffset, ypos, pix_width, pix_height, pixmap)) xoffset += pix_width + self._componentSizes.get(self.KEY_PICON_OFFSET, 8) if self.mode != self.MODE_NORMAL: # servicenumber if not (service.flags & eServiceReference.isMarker) and showListNumbers: markers_before = self.l.getNumMarkersBeforeCurrent() text = "%d" % (self.numberoffset + index + 1 - markers_before) nameWidth = self._componentSizes.get(self.KEY_SERVICE_NUMBER_WIDTH, 50) res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, nameWidth , height, 1, RT_HALIGN_RIGHT|RT_VALIGN_CENTER, text, forgroundColor, forgroundColorSel, backgroundColor, backgroundColorSel)) xoffset += nameWidth + textOffset # picons if isPlayable and showPicons: picon = self._buildOptionEntryServicePicon(service) if bigPicons: pix_width = self._componentSizes.get(self.KEY_PICON_WIDTH_BIG, 108) else: pix_width = self._componentSizes.get(self.KEY_PICON_WIDTH, 58) if picon: res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, xoffset, 0, pix_width, height, picon)) xoffset += pix_width xoffset += self._componentSizes.get(self.KEY_PICON_OFFSET, 8) # progressbar between servicenumber and servicename if drawProgressbar and progressbarPosition == "0": res.append(self._buildOptionEntryProgressBar(event, xoffset, width, height)) xoffset += progressBarWidth addtimedisplay, addtimedisplayWidth = self._buildOptionEntryAddTimeDisplay(event, isPlayable, columnStyle) if columnStyle: rwidth = 0 # servicename if (isPlayable and showServiceName) or not isPlayable: if isPlayable: rwidth = servicenameWidth # space for servicename else: rwidth = width - xoffset # space for servicename res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, rwidth , height, 2, RT_HALIGN_LEFT|RT_VALIGN_CENTER, serviceName, forgroundColor, forgroundColorSel, backgroundColor, backgroundColorSel)) xoffset += rwidth + textOffset # progressbar between servicename and service description if drawProgressbar and progressbarPosition == "1": res.append(self._buildOptionEntryProgressBar(event, xoffset, width, height)) xoffset += progressBarWidth if event and isPlayable: rwidth = width - xoffset if drawProgressbar and progressbarPosition == "2": rwidth -= self._progressBarWidth(withOffset=True, withProgressBarSize=False) rwidth -= self._progressBarWidth(withOffset=True, withProgressBarSize=True) if addtimedisplay != "" : if additionalposition == "0": # add time text before service description res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, addtimedisplayWidth, height, 0, RT_HALIGN_RIGHT|RT_VALIGN_CENTER, addtimedisplay, additionalInfoColor, additionalInfoColorSelected, backgroundColor, backgroundColorSel)) addoffset = addtimedisplayWidth + textOffset xoffset += addoffset rwidth -= addoffset elif additionalposition == "1": rwidth -= addtimedisplayWidth + textOffset # service description if secondlineinfo != "0" and self.mode == self.MODE_FAVOURITES: res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, rwidth, self.serviceInfoHeight, 3, RT_HALIGN_LEFT|RT_VALIGN_CENTER, event.getEventName(), serviceDescriptionColor, serviceDescriptionColorSelected, backgroundColor, backgroundColorSel)) if secondlineinfo == "1": # shortdescription text = event.getShortDescription() else: event_next = eEPGCache.getInstance().lookupEventTime(service, -1, 1) if event_next: beginTime = localtime(event_next.getBeginTime()) endTime = localtime(event_next.getBeginTime()+event_next.getDuration()) text = "%02d:%02d - %02d:%02d %s" % (beginTime[3],beginTime[4],endTime[3],endTime[4], event_next.getEventName()) else: text = "%s: n/a" % _("upcoming event") res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, self.serviceInfoHeight, rwidth, height - self.serviceInfoHeight, 0, RT_HALIGN_LEFT|RT_VALIGN_CENTER, text, additionalInfoColor, additionalInfoColorSelected, backgroundColor, backgroundColorSel)) else: res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, rwidth, height, 3, RT_HALIGN_LEFT|RT_VALIGN_CENTER, event.getEventName(), serviceDescriptionColor, serviceDescriptionColorSelected, backgroundColor, backgroundColorSel)) # progressbar after service description xoffset += rwidth if drawProgressbar and progressbarPosition == "2": xoffset += self._progressBarWidth(withOffset=True, withProgressBarSize=False) res.append(self._buildOptionEntryProgressBar(event, xoffset, width, height)) xoffset += progressBarWidth # add time text at last position if addtimedisplay != "" and additionalposition == "1": xoffset += textOffset res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, addtimedisplayWidth , height, 0, RT_HALIGN_RIGHT|RT_VALIGN_CENTER, addtimedisplay, additionalInfoColor, additionalInfoColorSelected, backgroundColor, backgroundColorSel)) else: if event and isPlayable: maxLength = width - xoffset if drawProgressbar and progressbarPosition == "2": # progressbar after service description maxLength -= progressBarWidth length = self._calcTextWidth(serviceName, font=self.serviceNameFont, size=eSize(maxLength,0)) + textOffset res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, length , height, 2, RT_HALIGN_LEFT|RT_VALIGN_CENTER, serviceName, forgroundColor, forgroundColorSel, backgroundColor, backgroundColorSel)) xoffset += length if addtimedisplay != "": if additionalposition == "1": # add time text after service description text = "(%s %s)" % (event.getEventName(), addtimedisplay) else: # add time text before service description text = "(%s %s)" % (addtimedisplay, event.getEventName()) else: text = "(%s)" % (event.getEventName()) length = width - xoffset if drawProgressbar and progressbarPosition == "2": # progressbar after service description length -= progressBarWidth # service description res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, length , height, 3, RT_HALIGN_LEFT|RT_VALIGN_CENTER, text, serviceDescriptionColor, serviceDescriptionColorSelected, backgroundColor, backgroundColorSel)) if drawProgressbar and progressbarPosition == "2": xoffset += length + textOffset / 2 res.append(self._buildOptionEntryProgressBar(event, xoffset, width, height)) else: res.append((eListboxPythonMultiContent.TYPE_TEXT, xoffset, 0, width - xoffset , height, 2, RT_HALIGN_LEFT|RT_VALIGN_CENTER, serviceName, forgroundColor, forgroundColorSel, backgroundColor, backgroundColorSel)) return res def applySkin(self, desktop, parent): attribs = [ ] for (attrib, value) in self.skinAttributes: if attrib == "foregroundColorMarked": self.markedForeground = parseColor(value) elif attrib == "foregroundColorMarkedSelected": self.markedForegroundSelected = parseColor(value) elif attrib == "backgroundColorMarked": self.markedBackground = parseColor(value) elif attrib == "backgroundColorMarkedSelected": self.markedBackgroundSelected = parseColor(value) elif attrib == "foregroundColorServiceNotAvail": self.serviceNotAvail = parseColor(value) elif attrib == "colorEventProgressbar": self.serviceEventProgressbarColor = parseColor(value) elif attrib == "colorEventProgressbarSelected": self.serviceEventProgressbarColorSelected = parseColor(value) elif attrib == "forgroundColorEventProgressbarBorder": self.serviceEventProgressbarBackColor = parseColor(value) elif attrib == "backgroundColorEventProgressbarBorderSelected": self.serviceEventProgressbarBackColorSelected = parseColor(value) elif attrib == "colorEventProgressbarBorder": self.serviceEventProgressbarBorderColor = parseColor(value) elif attrib == "colorEventProgressbarBorderSelected": self.serviceEventProgressbarBorderColorSelected = parseColor(value) elif attrib == "colorServiceDescription": self.serviceDescriptionColor = parseColor(value) elif attrib == "colorServiceDescriptionSelected": self.serviceDescriptionColorSelected = parseColor(value) elif attrib == "colorRecording": self.recordingColor = parseColor(value) elif attrib == "colorRecordingSelected": self.recordingColorSelected = parseColor(value) elif attrib == "colorAdditionalInfo": self.additionalInfoColor = parseColor(value) elif attrib == "colorAdditionalInfoSelected": self.additionalInfoColorSelected = parseColor(value) elif attrib == "picServiceEventProgressbar": pic = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, value)) if pic: self.picServiceEventProgressbar = pic elif attrib == "serviceItemHeight": self.itemHeight = int(value) elif attrib == "serviceItemHeightHigh": self.itemHeightHigh = int(value) elif attrib == "serviceNameFont": self.l.setFont(2, parseFont(value, ((1,1),(1,1)))) self.serviceNameFont = parseFont(value, ((1,1),(1,1))) elif attrib == "serviceInfoFont": self.l.setFont(3, parseFont(value, ((1,1),(1,1)))) name, size = value.split(';') self.serviceInfoFontHeight = int(size) elif attrib == "serviceNumberFont": self.l.setFont(1, parseFont(value, ((1,1),(1,1)))) elif attrib == "additionalInfoFont": self.l.setFont(0, parseFont(value, ((1,1),(1,1)))) self.additionalInfoFont = parseFont(value, ((1,1),(1,1))) elif attrib == "selectionPixmap": pic = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, value)) if pic: self.selectionPixmapStandard = pic if not config.usage.configselection_bigpicons.value: self.instance.setSelectionPicture(self.selectionPixmapStandard) elif attrib == "selectionPixmapHigh": pic = LoadPixmap(resolveFilename(SCOPE_CURRENT_SKIN, value)) if pic: self.selectionPixmapBig = pic if config.usage.configselection_bigpicons.value: self.instance.setSelectionPicture(self.selectionPixmapBig) else: attribs.append((attrib, value)) self.skinAttributes = attribs return GUIComponent.applySkin(self, desktop, parent) def connectSelChanged(self, fnc): if not fnc in self.onSelectionChanged: self.onSelectionChanged.append(fnc) def disconnectSelChanged(self, fnc): if fnc in self.onSelectionChanged: self.onSelectionChanged.remove(fnc) def selectionChanged(self): for x in self.onSelectionChanged: x() def setCurrent(self, ref): self.l.setCurrent(ref) def getCurrent(self): r = eServiceReference() self.l.getCurrent(r) return r def atBegin(self): return self.instance.atBegin() def atEnd(self): return self.instance.atEnd() def moveUp(self): self.instance.moveSelection(self.instance.moveUp) def moveDown(self): self.instance.moveSelection(self.instance.moveDown) def moveToChar(self, char): Log.d("Next char: %s" %(char,)) index = self.l.getNextBeginningWithChar(char) indexup = self.l.getNextBeginningWithChar(char.upper()) if indexup != 0: if (index > indexup or index == 0): index = indexup self.instance.moveSelectionTo(index) Log.i("Moving to character %s" %(char,)) def moveToNextMarker(self): idx = self.l.getNextMarkerPos() self.instance.moveSelectionTo(idx) def moveToPrevMarker(self): idx = self.l.getPrevMarkerPos() self.instance.moveSelectionTo(idx) def moveToIndex(self, index): self.instance.moveSelectionTo(index) def getCurrentIndex(self): return self.instance.getCurrentIndex() GUI_WIDGET = eListbox def postWidgetCreate(self, instance): instance.setWrapAround(True) instance.setContent(self.l) self.selectionChanged_conn = instance.selectionChanged.connect(self.selectionChanged) self.setMode(self.mode) self.textRenderer = eLabel(self.instance) self.textRenderer.resize(eSize(self.getDesktopWith() / 3, 0)) self.textRenderer.hide() def preWidgetRemove(self, instance): if self.session: self.session.nav.RecordTimer.on_state_change.remove(self.onTimerEntryStateChange) instance.setContent(None) self.selectionChanged_conn = None config.usage.configselection_showrecordings.removeNotifier(self.getRecordingList) config.usage.configselection_bigpicons.removeNotifier(self.setItemHeight) config.usage.configselection_secondlineinfo.removeNotifier(self.setItemHeight) self.piconLoader.finish() def getRoot(self): return self.root def getRootServices(self): serviceHandler = eServiceCenter.getInstance() list = serviceHandler.list(self.root) dest = [ ] if list is not None: while 1: s = list.getNext() if s.valid(): dest.append(s.toString()) else: break return dest def setNumberOffset(self, offset): self.numberoffset = offset def setPlayableIgnoreService(self, ref): self.is_playable_ignore = ref def setRoot(self, root, justSet=False): self.root = root self.l.setRoot(root, justSet) if not justSet: self.l.sort() self.selectionChanged() def removeCurrent(self): self.l.removeCurrent() def addService(self, service, beforeCurrent=False): self.l.addService(service, beforeCurrent) def finishFill(self): self.l.FillFinished() self.l.sort() # stuff for multiple marks (edit mode / later multiepg) def clearMarks(self): self.l.initMarked() def isMarked(self, ref): return self.l.isMarked(ref) def addMarked(self, ref): self.l.addMarked(ref) def removeMarked(self, ref): self.l.removeMarked(ref) def getMarked(self): i = self.l i.markedQueryStart() ref = eServiceReference() marked = [ ] while i.markedQueryNext(ref) == 0: marked.append(ref.toString()) ref = eServiceReference() return marked #just for movemode.. only one marked entry.. def setCurrentMarked(self, state): self.l.setCurrentMarked(state) def setMode(self, mode): self.mode = mode self.setItemHeight()
class PowerTimerList(GUIComponent, object): # # | <Service> <Name of the Timer> | # | <start, end> <state> | # def buildTimerEntry(self, timer, processed): screenwidth = getDesktop(0).size().width() timertype = { TIMERTYPE.WAKEUP: _("Wake Up"), TIMERTYPE.WAKEUPTOSTANDBY: _("Wake Up To Standby"), TIMERTYPE.STANDBY: _("Standby"), TIMERTYPE.AUTOSTANDBY: _("Auto Standby"), TIMERTYPE.AUTODEEPSTANDBY: _("Auto Deep Standby"), TIMERTYPE.DEEPSTANDBY: _("Deep Standby"), TIMERTYPE.REBOOT: _("Reboot"), TIMERTYPE.RESTART: _("Restart GUI") }[timer.timerType] afterevent = { AFTEREVENT.NONE: _("Nothing"), AFTEREVENT.WAKEUPTOSTANDBY: _("Wake Up To Standby"), AFTEREVENT.STANDBY: _("Standby"), AFTEREVENT.DEEPSTANDBY: _("Deep Standby") }[timer.afterEvent] height = self.l.getItemSize().height() width = self.l.getItemSize().width() res = [None] x = width / 2 res.append((eListboxPythonMultiContent.TYPE_TEXT, self.iconWidth + self.iconMargin, 2, width, self.rowSplit, 0, RT_HALIGN_LEFT | RT_VALIGN_BOTTOM, timertype)) if timer.timerType == TIMERTYPE.AUTOSTANDBY or timer.timerType == TIMERTYPE.AUTODEEPSTANDBY: if self.iconRepeat and timer.autosleeprepeat != "once": res.append( (eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, self.iconMargin / 2, self.rowSplit + (self.itemHeight - self.rowSplit - self.iconHeight) / 2, self.iconWidth, self.iconHeight, self.iconRepeat)) icon = None if not processed: if timer.state == TimerEntry.StateWaiting: state = _("waiting") icon = self.iconWait elif timer.state == TimerEntry.StatePrepared or timer.state == TimerEntry.StateRunning: state = _("running...") icon = self.iconZapped elif timer.state == TimerEntry.StateEnded: state = _("done!") icon = self.iconDone else: state = _("<unknown>") icon = None else: state = _("done!") icon = self.iconDone res.append((eListboxPythonMultiContent.TYPE_TEXT, 148, 26, width - 150, self.itemHeight - self.rowSplit, 2, RT_HALIGN_RIGHT | RT_VALIGN_BOTTOM, _("Delay:") + " " + str(timer.autosleepdelay) + "(" + _("mins") + ")")) else: res.append((eListboxPythonMultiContent.TYPE_TEXT, x + 24, 2, x - 2 - 24, self.itemHeight - self.rowSplit, 2, RT_HALIGN_RIGHT | RT_VALIGN_BOTTOM, _('At End:') + ' ' + afterevent)) days = (_("Mon"), _("Tue"), _("Wed"), _("Thu"), _("Fri"), _("Sat"), _("Sun")) begin = FuzzyTime(timer.begin) if timer.repeated: repeatedtext = [] flags = timer.repeated for x in (0, 1, 2, 3, 4, 5, 6): if flags & 1 == 1: repeatedtext.append(days[x]) flags >>= 1 if repeatedtext == [ _("Mon"), _("Tue"), _("Wed"), _("Thu"), _("Fri"), _("Sat"), _("Sun") ]: repeatedtext = _('Everyday') elif repeatedtext == [ _("Mon"), _("Tue"), _("Wed"), _("Thu"), _("Fri") ]: repeatedtext = _('Weekday') elif repeatedtext == [_("Sat"), _("Sun")]: repeatedtext = _('Weekend') else: repeatedtext = ", ".join(repeatedtext) if self.iconRepeat: res.append( (eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, 2, self.rowSplit, 20, 20, self.iconRepeat)) else: repeatedtext = begin[0] # date text = repeatedtext + ((" %s ... %s (%d " + _("mins") + ")") % (begin[1], FuzzyTime(timer.end)[1], (timer.end - timer.begin) / 60)) res.append( (eListboxPythonMultiContent.TYPE_TEXT, 148, self.itemHeight - self.rowSplit, width - 150, self.rowSplit, 2, RT_HALIGN_RIGHT | RT_VALIGN_BOTTOM, text)) icon = None if not processed: if timer.state == TimerEntry.StateWaiting: state = _("waiting") icon = self.iconWait elif timer.state == TimerEntry.StatePrepared: state = _("about to start") icon = self.iconPrepared elif timer.state == TimerEntry.StateRunning: state = _("running...") icon = self.iconZapped elif timer.state == TimerEntry.StateEnded: state = _("done!") icon = self.iconDone else: state = _("<unknown>") icon = None else: state = _("done!") icon = self.iconDone if timer.disabled: state = _("disabled") icon = self.iconDisabled if timer.failed: state = _("failed") icon = self.iconFailed icon and res.append( (eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, self.iconMargin / 2, (self.rowSplit - self.iconHeight) / 2, self.iconWidth, self.iconHeight, icon)) res.append((eListboxPythonMultiContent.TYPE_TEXT, self.iconMargin + self.iconWidth, self.rowSplit, 126, height - self.rowSplit, 2, RT_HALIGN_LEFT | RT_VALIGN_BOTTOM, state)) line = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, "div-h.png")) res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, 0, height - 2, width, 2, line)) return res def __init__(self, list): GUIComponent.__init__(self) self.l = eListboxPythonMultiContent() self.l.setBuildFunc(self.buildTimerEntry) self.serviceNameFont = gFont("Regular", 20) self.font = gFont("Regular", 18) self.eventNameFont = gFont("Regular", 18) self.l.setList(list) self.itemHeight = 50 self.rowSplit = 25 self.iconMargin = 4 self.satPosLeft = 160 self.iconWait = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, "icons/timer_wait.png")) self.iconWidth = self.iconWait.size().width() self.iconHeight = self.iconWait.size().height() self.iconRecording = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, "icons/timer_rec.png")) self.iconPrepared = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, "icons/timer_prep.png")) self.iconDone = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, "icons/timer_done.png")) self.iconRepeat = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, "icons/timer_rep.png")) self.iconZapped = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, "icons/timer_zap.png")) self.iconDisabled = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, "icons/timer_off.png")) self.iconFailed = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, "icons/timer_failed.png")) def applySkin(self, desktop, parent): def itemHeight(value): self.itemHeight = int(value) def setServiceNameFont(value): self.serviceNameFont = parseFont(value, ((1, 1), (1, 1))) def setEventNameFont(value): self.eventNameFont = parseFont(value, ((1, 1), (1, 1))) def setFont(value): self.font = parseFont(value, ((1, 1), (1, 1))) def rowSplit(value): self.rowSplit = int(value) def iconMargin(value): self.iconMargin = int(value) def satPosLeft(value): self.satPosLeft = int(value) for (attrib, value) in list(self.skinAttributes): try: locals().get(attrib)(value) self.skinAttributes.remove((attrib, value)) except: pass self.l.setItemHeight(self.itemHeight) self.l.setFont(0, self.serviceNameFont) self.l.setFont(1, self.font) self.l.setFont(2, self.eventNameFont) return GUIComponent.applySkin(self, desktop, parent) def getCurrent(self): cur = self.l.getCurrentSelection() return cur and cur[0] GUI_WIDGET = eListbox def postWidgetCreate(self, instance): instance.setContent(self.l) self.instance = instance def moveToIndex(self, index): self.instance.moveSelectionTo(index) def getCurrentIndex(self): return self.instance.getCurrentIndex() currentIndex = property(getCurrentIndex, moveToIndex) currentSelection = property(getCurrent) def moveDown(self): self.instance.moveSelection(self.instance.moveDown) def invalidate(self): self.l.invalidate() def entryRemoved(self, idx): self.l.entryRemoved(idx)
class PowerTimerList(HTMLComponent, GUIComponent, object): # # | <Service> <Name of the Timer> | # | <start, end> <state> | # def buildTimerEntry(self, timer, processed): screenwidth = getDesktop(0).size().width() height = self.l.getItemSize().height() width = self.l.getItemSize().width() res = [None] x = width / 2 if screenwidth and screenwidth == 1920: res.append( (eListboxPythonMultiContent.TYPE_TEXT, 39, 3, width, 38, 2, RT_HALIGN_LEFT | RT_VALIGN_BOTTOM, gettimerType(timer))) else: res.append( (eListboxPythonMultiContent.TYPE_TEXT, 26, 3, width, 25, 0, RT_HALIGN_LEFT | RT_VALIGN_BOTTOM, gettimerType(timer))) if timer.timerType == TIMERTYPE.AUTOSTANDBY or timer.timerType == TIMERTYPE.AUTODEEPSTANDBY: if self.iconRepeat and timer.autosleeprepeat != "once": if screenwidth and screenwidth == 1920: res.append( (eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, 3, 5, 30, 30, self.iconRepeat)) else: res.append( (eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, 2, 3, 20, 20, self.iconRepeat)) icon = None if not processed: if timer.state == TimerEntry.StateWaiting: state = _("waiting") icon = self.iconWait elif timer.state == TimerEntry.StatePrepared or timer.state == TimerEntry.StateRunning: state = _("running...") icon = self.iconZapped elif timer.state == TimerEntry.StateEnded: state = _("done!") icon = self.iconDone else: state = _("<unknown>") icon = None else: state = _("done!") icon = self.iconDone autosleepwindow = "" if timer.autosleepwindow == 'yes': autosleepwindow = _("Time range:") + " " + FuzzyTime( timer.autosleepbegin)[1] + " ... " + FuzzyTime( timer.autosleepend)[1] + ", " if screenwidth and screenwidth == 1920: res.append( (eListboxPythonMultiContent.TYPE_TEXT, 225, 38, width - 225, 35, 3, RT_HALIGN_RIGHT | RT_VALIGN_BOTTOM, autosleepwindow + _("Delay:") + " " + str(timer.autosleepdelay) + "(" + _("mins") + ")")) else: res.append( (eListboxPythonMultiContent.TYPE_TEXT, 150, 26, width - 150, 23, 1, RT_HALIGN_RIGHT | RT_VALIGN_BOTTOM, autosleepwindow + _("Delay:") + " " + str(timer.autosleepdelay) + "(" + _("mins") + ")")) else: if screenwidth and screenwidth == 1920: res.append( (eListboxPythonMultiContent.TYPE_TEXT, x + 36, 3, x - 3 - 36, 35, 3, RT_HALIGN_RIGHT | RT_VALIGN_BOTTOM, _('At End:') + ' ' + getafterEvent(timer))) else: res.append( (eListboxPythonMultiContent.TYPE_TEXT, x + 24, 3, x - 2 - 24, 23, 1, RT_HALIGN_RIGHT | RT_VALIGN_BOTTOM, _('At End:') + ' ' + getafterEvent(timer))) days = (_("Mon"), _("Tue"), _("Wed"), _("Thu"), _("Fri"), _("Sat"), _("Sun")) begin = FuzzyTime(timer.begin) if timer.repeated: days = (_("Mon"), _("Tue"), _("Wed"), _("Thu"), _("Fri"), _("Sat"), _("Sun")) repeatedtext = [] flags = timer.repeated for x in (0, 1, 2, 3, 4, 5, 6): if flags & 1 == 1: repeatedtext.append(days[x]) flags >>= 1 repeatedtext = ", ".join(repeatedtext) if self.iconRepeat: if screenwidth and screenwidth == 1920: res.append( (eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, 3, 5, 30, 30, self.iconRepeat)) else: res.append( (eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, 2, 3, 20, 20, self.iconRepeat)) else: repeatedtext = begin[0] # date text = repeatedtext + ((" %s ... %s (%d " + _("mins") + ")") % (begin[1], FuzzyTime(timer.end)[1], (timer.end - timer.begin) / 60)) if screenwidth and screenwidth == 1920: res.append((eListboxPythonMultiContent.TYPE_TEXT, 225, 38, width - 225, 35, 3, RT_HALIGN_RIGHT | RT_VALIGN_BOTTOM, text)) else: res.append((eListboxPythonMultiContent.TYPE_TEXT, 150, 26, width - 150, 23, 1, RT_HALIGN_RIGHT | RT_VALIGN_BOTTOM, text)) icon = None if not processed: if timer.state == TimerEntry.StateWaiting: state = _("waiting") icon = self.iconWait elif timer.state == TimerEntry.StatePrepared: state = _("about to start") icon = self.iconPrepared elif timer.state == TimerEntry.StateRunning: state = _("running...") icon = self.iconZapped elif timer.state == TimerEntry.StateEnded: state = _("done!") icon = self.iconDone else: state = _("<unknown>") icon = None else: state = _("done!") icon = self.iconDone if timer.disabled: state = _("disabled") icon = self.iconDisabled if timer.failed: state = _("failed") icon = self.iconFailed if screenwidth and screenwidth == 1920: res.append((eListboxPythonMultiContent.TYPE_TEXT, 39, 38, 225, 35, 3, RT_HALIGN_LEFT | RT_VALIGN_BOTTOM, state)) else: res.append((eListboxPythonMultiContent.TYPE_TEXT, 26, 26, 150, 23, 1, RT_HALIGN_LEFT | RT_VALIGN_BOTTOM, state)) if icon: if screenwidth and screenwidth == 1920: res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, 3, 39, 30, 30, icon)) else: res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, 2, 26, 20, 20, icon)) line = LoadPixmap(resolveFilename(SCOPE_ACTIVE_SKIN, "div-h.png")) res.append((eListboxPythonMultiContent.TYPE_PIXMAP_ALPHABLEND, 0, height - 2, width, 2, line)) return res def __init__(self, list): GUIComponent.__init__(self) self.l = eListboxPythonMultiContent() self.l.setBuildFunc(self.buildTimerEntry) self.serviceNameFont = gFont("Regular", 20) self.font = gFont("Regular", 18) self.eventNameFont = gFont("Regular", 18) self.l.setFont(0, gFont("Regular", 20)) self.l.setFont(1, gFont("Regular", 18)) self.l.setFont(2, gFont("Regular", 30)) self.l.setFont(3, gFont("Regular", 27)) self.l.setItemHeight(50) self.l.setList(list) self.itemHeight = 50 self.rowSplit = 25 self.iconMargin = 4 self.satPosLeft = 160 self.iconWait = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, "icons/timer_wait.png")) self.iconWidth = self.iconWait.size().width() self.iconHeight = self.iconWait.size().height() self.iconRecording = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, "icons/timer_rec.png")) self.iconPrepared = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, "icons/timer_prep.png")) self.iconDone = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, "icons/timer_done.png")) self.iconRepeat = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, "icons/timer_rep.png")) self.iconZapped = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, "icons/timer_zap.png")) self.iconDisabled = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, "icons/timer_off.png")) self.iconFailed = LoadPixmap( resolveFilename(SCOPE_ACTIVE_SKIN, "icons/timer_failed.png")) def applySkin(self, desktop, parent): def itemHeight(value): self.itemHeight = int(value) def setServiceNameFont(value): self.serviceNameFont = parseFont(value, ((1, 1), (1, 1))) def setEventNameFont(value): self.eventNameFont = parseFont(value, ((1, 1), (1, 1))) def setFont(value): self.font = parseFont(value, ((1, 1), (1, 1))) def rowSplit(value): self.rowSplit = int(value) def iconMargin(value): self.iconMargin = int(value) def satPosLeft(value): self.satPosLeft = int(value) for (attrib, value) in list(self.skinAttributes): try: locals().get(attrib)(value) self.skinAttributes.remove((attrib, value)) except: pass self.l.setItemHeight(self.itemHeight) self.l.setFont(0, self.serviceNameFont) self.l.setFont(1, self.font) self.l.setFont(2, self.eventNameFont) return GUIComponent.applySkin(self, desktop, parent) def getCurrent(self): cur = self.l.getCurrentSelection() return cur and cur[0] GUI_WIDGET = eListbox def postWidgetCreate(self, instance): instance.setContent(self.l) self.instance = instance def moveToIndex(self, index): self.instance.moveSelectionTo(index) def getCurrentIndex(self): return self.instance.getCurrentIndex() currentIndex = property(getCurrentIndex, moveToIndex) currentSelection = property(getCurrent) def moveDown(self): self.instance.moveSelection(self.instance.moveDown) def invalidate(self): self.l.invalidate() def entryRemoved(self, idx): self.l.entryRemoved(idx)