示例#1
0
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
示例#3
0
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
示例#4
0
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
示例#5
0
	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
示例#6
0
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
示例#7
0
    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
示例#8
0
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
示例#9
0
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
示例#11
0
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
示例#12
0
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
示例#13
0
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
示例#16
0
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
示例#17
0
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)
示例#18
0
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
示例#19
0
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())
示例#20
0
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)
示例#21
0
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
示例#22
0
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
示例#23
0
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
示例#24
0
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)
示例#25
0
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
示例#26
0
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()
示例#27
0
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)
示例#28
0
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
示例#29
0
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
示例#30
0
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
示例#31
0
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
示例#33
0
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
示例#34
0
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
示例#35
0
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)
示例#36
0
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
示例#37
0
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
示例#38
0
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)
示例#39
0
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
示例#40
0
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()
示例#41
0
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)
示例#42
0
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)