From 927bc8100e1670fd98939238bb27fa4b448815f8 Mon Sep 17 00:00:00 2001 From: Alhaziel Date: Fri, 24 May 2019 16:01:32 +0200 Subject: [PATCH] Moved to specials --- channels/cloudvideo.py | 36 - specials/autorenumber.py | 1 + {channels => specials}/community.json | 0 {channels => specials}/community.py | 0 specials/renumbertools.py | 1001 ++++++++++++++++++++++++ {channels => specials}/trailertools.py | 0 6 files changed, 1002 insertions(+), 36 deletions(-) delete mode 100644 channels/cloudvideo.py rename {channels => specials}/community.json (100%) rename {channels => specials}/community.py (100%) create mode 100644 specials/renumbertools.py rename {channels => specials}/trailertools.py (100%) diff --git a/channels/cloudvideo.py b/channels/cloudvideo.py deleted file mode 100644 index e8652eeb..00000000 --- a/channels/cloudvideo.py +++ /dev/null @@ -1,36 +0,0 @@ -# Conector Cloudvideo By Alfa development Group -# -------------------------------------------------------- - -import re -from core import httptools -from core import scrapertools -from lib import jsunpack -from platformcode import logger - - -def test_video_exists(page_url): - logger.info("(page_url='%s')" % page_url) - data = httptools.downloadpage(page_url) - if data.code == 404: - return False, "[Cloud] El archivo no existe o ha sido borrado" - return True, "" - - -def get_video_url(page_url, premium=False, user="", password="", video_password=""): - logger.info("url=" + page_url) - video_urls = [] - data = httptools.downloadpage(page_url).data - enc_data = scrapertools.find_single_match(data, "type='text/javascript'>(.*?)") - dec_data = jsunpack.unpack(enc_data) - sources = scrapertools.find_single_match(data, "= S: if E == 0: epList.append([0, SP]) diff --git a/channels/community.json b/specials/community.json similarity index 100% rename from channels/community.json rename to specials/community.json diff --git a/channels/community.py b/specials/community.py similarity index 100% rename from channels/community.py rename to specials/community.py diff --git a/specials/renumbertools.py b/specials/renumbertools.py new file mode 100644 index 00000000..89a391ac --- /dev/null +++ b/specials/renumbertools.py @@ -0,0 +1,1001 @@ +# -*- coding: utf-8 -*- +# -------------------------------------------------------------------------------- +# renumeratetools - se encarga de renumerar episodios +# -------------------------------------------------------------------------------- + +import os + +try: + import xbmcgui +except: + xbmcgui = None + +from platformcode import config, logger +from core import jsontools +from core.item import Item +from platformcode import platformtools + +TAG_TVSHOW_RENUMERATE = "TVSHOW_RENUMBER" +TAG_SEASON_EPISODE = "season_episode" +__channel__ = "renumbertools" + + +def access(): + """ + Devuelve si se puede usar o no renumbertools + """ + allow = False + + if config.is_xbmc(): + allow = True + + return allow + + +def context(item): + """ + Para xbmc/kodi que pueden mostrar el menú contextual, se añade un menu para configuración + la opción de renumerar, sólo si es para series. + + @param item: elemento para obtener la información y ver que contexto añadir + @type item: item + @return: lista de opciones a mostrar en el menú contextual + @rtype: list + """ + + # Dependiendo de como sea el contexto lo guardamos y añadimos las opciones de filtertools. + if type(item.context) == str: + _context = item.context.split("|") + elif type(item.context) == list: + _context = item.context + else: + _context = [] + + if access(): + dict_data = {"title": config.get_localized_string(70585), "action": "config_item", "channel": "renumbertools"} + _context.append(dict_data) + + return _context + + +def show_option(channel, itemlist): + if access(): + itemlist.append(Item(channel=__channel__, title="[COLOR yellow]" + config.get_localized_string(70586)+ "[/COLOR]", + action="load", from_channel=channel)) + + return itemlist + + +def load(item): + return mainlist(channel=item.from_channel) + + +def mainlist(channel): + """ + Muestra una lista de las series renumeradas + + :param channel: nombre del canal para obtener las series renumeradas + :type channel: str + :return: lista de Item + :rtype: list[Item] + """ + logger.info() + itemlist = [] + dict_series = jsontools.get_node_from_file(channel, TAG_TVSHOW_RENUMERATE) + + idx = 0 + for tvshow in sorted(dict_series): + tag_color = "0xff008000" + if idx % 2 == 0: + tag_color = "blue" + + idx += 1 + name = tvshow + title = config.get_localized_string(70587)+" [COLOR %s][%s][/COLOR]" % (tag_color, name) + + itemlist.append(Item(channel=__channel__, action="config_item", title=title, show=name, from_channel=channel)) + + if len(itemlist) == 0: + itemlist.append(Item(channel=channel, action="mainlist", + title=config.get_localized_string(70588) + ' ' + config.get_localized_string(70585))) + + return itemlist + + +def config_item(item): + """ + muestra una serie renumerada para su configuración + + :param item: item + :type item: Item + """ + logger.info("item %s" % item.tostring("\n")) + + dict_series = jsontools.get_node_from_file(item.from_channel, TAG_TVSHOW_RENUMERATE) + data = dict_series.get(item.show, {}) + + if data: + data = data.get(TAG_SEASON_EPISODE, []) + + ventana = RenumberWindow(show=item.show, channel=item.from_channel, data=data) + del ventana + else: + # tenemos información y devolvemos los datos añadidos para que se muestre en la ventana + if data: + return add_season(data) + # es la primera vez que se añaden datos (usando menú contextual) por lo que no devolvemos nada + # para evitar error al listar los items + else: + data = add_season(data) + write_data(item.from_channel, item.show, data) + + +def numbered_for_tratk(channel, show, season, episode): + """ + Devuelve la temporada y episodio convertido para que se marque correctamente en tratk.tv + + @param channel: Nombre del canal + @type channel: str + @param show: Nombre de la serie a comprobar + @type show: str + @param season: Temporada que devuelve el scrapper + @type season: int + @param episode: Episodio que devuelve el scrapper + @type episode: int + @return: season, episode + @rtype: int, int + """ + logger.info() + + if access(): + show = show.lower() + + new_season = season + new_episode = episode + dict_series = jsontools.get_node_from_file(channel, TAG_TVSHOW_RENUMERATE) + + # ponemos en minusculas el key, ya que previamente hemos hecho lo mismo con show. + for key in dict_series.keys(): + new_key = key.lower() + if new_key != key: + dict_series[new_key] = dict_series[key] + del dict_series[key] + + if show in dict_series: + logger.debug(config.get_localized_string(70589) + " %s" % dict_series[show]) + + if len(dict_series[show]['season_episode']) > 1: + for row in dict_series[show]['season_episode']: + + if new_episode > row[1]: + new_episode -= row[1] + new_season = row[0] + break + + else: + new_season = dict_series[show]['season_episode'][0][0] + new_episode += dict_series[show]['season_episode'][0][1] + + logger.debug("%s:%s" % (new_season, new_episode)) + else: + # no se tiene acceso se devuelven los datos. + new_season = season + new_episode = episode + + return new_season, new_episode + + +def borrar(channel, show): + logger.info() + heading = config.get_localized_string(70590) + line1 = config.get_localized_string(70591) + ' [COLOR blue]' + show.strip() + '[/COLOR], ' + config.get_localized_string(70592) + + if platformtools.dialog_yesno(heading, line1) == 1: + dict_series = jsontools.get_node_from_file(channel, TAG_TVSHOW_RENUMERATE) + dict_series.pop(show, None) + + result, json_data = jsontools.update_node(dict_series, channel, TAG_TVSHOW_RENUMERATE) + + if result: + message = config.get_localized_string(60444) + else: + message = config.get_localized_string(70593) + + heading = show.strip() + platformtools.dialog_notification(heading, message) + + +def add_season(data=None): + logger.debug("data %s" % data) + heading = config.get_localized_string(70594) + # default = 2 + # se reordena la lista + list_season_episode = data + if list_season_episode: + list_season_episode.sort(key=lambda el: int(el[0]), reverse=False) + + # if list_season_episode: + # # mostrar temporada + 1 de la lista + # # TODO buscar la primera posicion libre + # default = list_season_episode[0][0]+1 + + season = platformtools.dialog_numeric(0, heading) # , str(default)) + for element in list_season_episode: + if int(season) == element[0]: + platformtools.dialog_notification(config.get_localized_string(70595), config.get_localized_string(70596)) + return + + # si hemos insertado un valor en la temporada + if season != "" and int(season) > 0: + heading = config.get_localized_string(70597) + # default = 0 + # if list_season_episode: + # for e in list_season_episode: + # # mostrar suma episodios de la lista + # # sumar hasta el indice del primer libre encontrado + # default += e[1] + episode = platformtools.dialog_numeric(0, heading) # , str(default)) + + # si hemos insertado un valor en el episodio + if episode != "": + if list_season_episode: + list_season_episode.insert(0, [int(season), int(episode)]) + new_list_season_episode = list_season_episode[:] + return new_list_season_episode + else: + return [[int(season), int(episode)]] + + +def write_data(channel, show, data): + # OBTENEMOS LOS DATOS DEL JSON + dict_series = jsontools.get_node_from_file(channel, TAG_TVSHOW_RENUMERATE) + tvshow = show.strip() + list_season_episode = dict_series.get(tvshow, {}).get(TAG_SEASON_EPISODE, []) + logger.debug("data %s" % list_season_episode) + + if data: + # cambiamos el orden para que se vea en orden descendente y usarse bien en el _data.json + data.sort(key=lambda el: int(el[0]), reverse=True) + dict_renumerate = {TAG_SEASON_EPISODE: data} + + dict_series[tvshow] = dict_renumerate + else: + # hemos borrado todos los elementos, por lo que se borra la serie del fichero + dict_series.pop(tvshow, None) + + result, json_data = jsontools.update_node(dict_series, channel, TAG_TVSHOW_RENUMERATE) + + if result: + if data: + message = config.get_localized_string(60446) + else: + message = config.get_localized_string(60444) + else: + message = config.get_localized_string(70593) + + heading = show.strip() + platformtools.dialog_notification(heading, message) + + +if xbmcgui: + + # Align + ALIGN_LEFT = 0 + ALIGN_RIGHT = 1 + ALIGN_CENTER_X = 2 + ALIGN_CENTER_Y = 4 + ALIGN_CENTER = 6 + ALIGN_TRUNCATED = 8 + ALIGN_JUSTIFY = 10 + + # button ids + ID_BUTTON_CLOSE = 3003 + ID_BUTTON_ADD_SEASON = 3008 + ID_BUTTON_INFO = 3009 + ID_CHECK_UPDATE_INTERNET = 3010 + ID_BUTTON_OK = 3012 + ID_BUTTON_CANCEL = 3013 + ID_BUTTON_DELETE = 3014 + + + class RenumberWindow(xbmcgui.WindowDialog): + def __init__(self, *args, **kwargs): + logger.debug() + + #### Compatibilidad con Kodi 18 #### + if config.get_platform(True)['num_version'] < 18: + if xbmcgui.__version__ == "1.2": + self.setCoordinateResolution(1) + else: + self.setCoordinateResolution(5) + + self.show = kwargs.get("show") + self.channel = kwargs.get("channel") + self.data = kwargs.get("data") + self.init = True + + self.mediapath = os.path.join(config.get_runtime_path(), 'resources', 'skins', 'Default', 'media') + self.font = "font12" + + window_bg = xbmcgui.ControlImage(320, 130, 600, 440, + os.path.join(self.mediapath, 'Windows', 'DialogBack.png')) + self.addControl(window_bg) + + header_bg = xbmcgui.ControlImage(window_bg.getX(), window_bg.getY() + 8, window_bg.getWidth(), 35, + os.path.join(self.mediapath, 'Windows', 'dialogheader.png')) + self.addControl(header_bg) + + btn_close_w = 64 + self.btn_close = xbmcgui.ControlButton(window_bg.getX() + window_bg.getWidth() - btn_close_w - 13, + header_bg.getY() + 6, btn_close_w, 30, '', + focusTexture=os.path.join(self.mediapath, 'Controls', + 'DialogCloseButton-focus.png'), + noFocusTexture=os.path.join(self.mediapath, 'Controls', + 'DialogCloseButton.png')) + self.addControl(self.btn_close) + + header_title_x = window_bg.getX() + 20 + header_title = xbmcgui.ControlFadeLabel(header_title_x, header_bg.getY() + 5, self.btn_close.getX() - + header_title_x, 30, font="font12_title", textColor="0xFFFFA500", + _alignment=ALIGN_CENTER) + self.addControl(header_title) + header_title.addLabel(self.show) + + self.controls_bg = xbmcgui.ControlImage(window_bg.getX() + 20, header_bg.getY() + header_bg.getHeight() + 6, + 562, 260, + os.path.join(self.mediapath, 'Windows', 'BackControls.png')) + self.addControl(self.controls_bg) + + self.scroll_bg = xbmcgui.ControlImage(window_bg.getX() + window_bg.getWidth() - 25, self.controls_bg.getY(), + 10, + self.controls_bg.getHeight(), os.path.join(self.mediapath, 'Controls', + 'ScrollBack.png')) + self.addControl(self.scroll_bg) + self.scroll_bg.setVisible(False) + + self.scroll2_bg = xbmcgui.ControlImage(window_bg.getX() + window_bg.getWidth() - 25, + self.controls_bg.getY(), + 10, self.controls_bg.getHeight(), os.path.join(self.mediapath, + 'Controls', + 'ScrollBar.png')) + self.addControl(self.scroll2_bg) + self.scroll2_bg.setVisible(False) + + btn_add_season = xbmcgui.ControlButton(window_bg.getX() + 20, self.controls_bg.getY() + + self.controls_bg.getHeight() + 14, 165, 30, config.get_localized_string(70600), + font=self.font, focusTexture=os.path.join(self.mediapath, 'Controls', + 'KeyboardKey.png'), + noFocusTexture=os.path.join(self.mediapath, 'Controls', + 'KeyboardKeyNF.png'), + alignment=ALIGN_CENTER) + self.addControl(btn_add_season) + + self.btn_info = xbmcgui.ControlButton(window_bg.getX() + 210, btn_add_season.getY(), 120, 30, config.get_localized_string(60348), + font=self.font, focusTexture=os.path.join(self.mediapath, 'Controls', + 'KeyboardKey.png'), + noFocusTexture=os.path.join(self.mediapath, 'Controls', + 'KeyboardKeyNF.png'), + alignment=ALIGN_CENTER) + self.addControl(self.btn_info) + + check_update_internet_w = 235 + # Versiones antiguas no admite algunas texturas + if xbmcgui.__version__ in ["1.2", "2.0"]: + self.check_update_internet = xbmcgui.ControlRadioButton( + window_bg.getX() + window_bg.getWidth() - check_update_internet_w - 20, btn_add_season.getY() - 3, + check_update_internet_w, 34, config.get_localized_string(70601), font=self.font, + focusTexture=os.path.join(self.mediapath, 'Controls', 'MenuItemFO.png'), + noFocusTexture=os.path.join(self.mediapath, 'Controls', 'MenuItemNF.png')) + else: + self.check_update_internet = xbmcgui.ControlRadioButton( + window_bg.getX() + window_bg.getWidth() - check_update_internet_w - 20, btn_add_season.getY() - 3, + check_update_internet_w, 34, config.get_localized_string(70601), font=self.font, + focusTexture=os.path.join(self.mediapath, 'Controls', 'MenuItemFO.png'), + noFocusTexture=os.path.join(self.mediapath, 'Controls', 'MenuItemNF.png'), + focusOnTexture=os.path.join(self.mediapath, 'Controls', 'radiobutton-focus.png'), + noFocusOnTexture=os.path.join(self.mediapath, 'Controls', 'radiobutton-focus.png'), + focusOffTexture=os.path.join(self.mediapath, 'Controls', 'radiobutton-nofocus.png'), + noFocusOffTexture=os.path.join(self.mediapath, 'Controls', 'radiobutton-nofocus.png')) + + self.addControl(self.check_update_internet) + self.check_update_internet.setEnabled(False) + + hb_bg = xbmcgui.ControlImage(window_bg.getX() + 20, btn_add_season.getY() + btn_add_season.getHeight() + 13, + window_bg.getWidth() - 40, 2, + os.path.join(self.mediapath, 'Controls', 'ScrollBack.png')) + self.addControl(hb_bg) + + self.btn_ok = xbmcgui.ControlButton(window_bg.getX() + 68, hb_bg.getY() + hb_bg.getHeight() + 13, 120, 30, + 'OK', font=self.font, + focusTexture=os.path.join(self.mediapath, 'Controls', + 'KeyboardKey.png'), + noFocusTexture=os.path.join(self.mediapath, 'Controls', + 'KeyboardKeyNF.png'), + alignment=ALIGN_CENTER) + self.addControl(self.btn_ok) + + self.btn_cancel = xbmcgui.ControlButton(self.btn_info.getX() + 30, self.btn_ok.getY(), 120, 30, config.get_localized_string(70002), + font=self.font, + focusTexture=os.path.join(self.mediapath, 'Controls', + 'KeyboardKey.png'), + noFocusTexture=os.path.join(self.mediapath, 'Controls', + 'KeyboardKeyNF.png'), + alignment=ALIGN_CENTER) + self.addControl(self.btn_cancel) + + self.btn_delete = xbmcgui.ControlButton(self.btn_cancel.getX() + self.btn_cancel.getWidth() + 50, + self.btn_ok.getY(), 120, 30, config.get_localized_string(60437), font=self.font, + focusTexture=os.path.join(self.mediapath, 'Controls', + 'KeyboardKey.png'), + noFocusTexture=os.path.join(self.mediapath, 'Controls', + 'KeyboardKeyNF.png'), + alignment=ALIGN_CENTER) + self.addControl(self.btn_delete) + + self.controls = [] + self.onInit() + self.setFocus(self.controls[0].edit_season) + self.doModal() + + def onInit(self, *args, **kwargs): + try: + # listado temporada / episodios + pos_y = self.controls_bg.getY() + 10 + + # eliminamos los componentes al repintar la ventana + for linea in self.controls: + self.removeControls(linea.list_elements()) + + # mostramos el scroll si hay más de 5 elementos + if len(self.data) > 5: + self.controls_bg.setWidth(545) + self.scroll_bg.setVisible(True) + self.scroll2_bg.setVisible(True) + else: + self.controls_bg.setWidth(562) + self.scroll_bg.setVisible(False) + self.scroll2_bg.setVisible(False) + + self.controls = [] + # cambiamos el orden para que se vea en orden ascendente + self.data.sort(key=lambda el: int(el[0]), reverse=False) + + for index, e in enumerate(self.data): + pos_x = self.controls_bg.getX() + 15 + label_season_w = 100 + label_season = xbmcgui.ControlLabel(pos_x, pos_y + 3, label_season_w, 34, + config.get_localized_string(60385), font=self.font, textColor="0xFF2E64FE") + self.addControl(label_season) + label_season.setVisible(False) + + pos_x += label_season_w + 5 + + # TODO mirar retro-compatilibidad + # if xbmcgui.ControlEdit == ControlEdit: + # edit_season = xbmcgui.ControlEdit(0, 0, 0, 0, '', font=self.font, isPassword=False, + # textColor='', + # focusTexture=os.path.join(self.mediapath, 'Controls', + # 'MenuItemFO.png'), + # noFocusTexture=os.path.join(self.mediapath, 'Controls', + # 'MenuItemNF.png'), window=self) + # else: + + # control bugeado se tiene que usar metodos sets para que se cree correctamente. + edit_season = xbmcgui.ControlEdit(0, 0, 0, 0, "", self.font, "", '', 4, isPassword=False, + focusTexture=os.path.join(self.mediapath, 'Controls', + 'MenuItemFO.png'), + noFocusTexture=os.path.join(self.mediapath, 'Controls', + 'MenuItemNF.png')) + self.addControl(edit_season) + edit_season.setText(str(e[0])) + # edit_season.setLabel("Temporada:", font=self.font, textColor="0xFF2E64FE") + edit_season.setPosition(pos_x, pos_y - 2) + edit_season.setWidth(25) + edit_season.setHeight(35) + edit_season.setVisible(False) + + label_episode_w = 90 + pos_x += edit_season.getWidth() + 60 + label_episode = xbmcgui.ControlLabel(pos_x, pos_y + 3, label_episode_w, 34, config.get_localized_string(70598), + font=self.font, textColor="0xFF2E64FE") + self.addControl(label_episode) + label_episode.setVisible(False) + + pos_x += label_episode_w + 5 + # control bugeado se tiene que usar metodos sets para que se cree correctamente. + edit_episode = xbmcgui.ControlEdit(0, 0, 0, 0, "", self.font, "", '', 4, isPassword=False, + focusTexture=os.path.join(self.mediapath, 'Controls', + 'MenuItemFO.png'), + noFocusTexture=os.path.join(self.mediapath, 'Controls', + 'MenuItemNF.png')) + self.addControl(edit_episode) + edit_episode.setText(str(e[1])) + # edit_episode.setLabel("Episodios:", font=self.font, textColor="0xFF2E64FE") + edit_episode.setPosition(pos_x, pos_y - 2) + edit_episode.setWidth(40) + edit_episode.setHeight(35) + edit_episode.setVisible(False) + + btn_delete_season_w = 120 + btn_delete_season = xbmcgui.ControlButton(self.controls_bg.getX() + self.controls_bg.getWidth() - + btn_delete_season_w - 14, pos_y, btn_delete_season_w, 30, + config.get_localized_string(70599), font=self.font, + focusTexture=os.path.join(self.mediapath, 'Controls', + 'KeyboardKey.png'), + noFocusTexture=os.path.join(self.mediapath, 'Controls', + 'KeyboardKeyNF.png'), + alignment=ALIGN_CENTER) + self.addControl(btn_delete_season) + btn_delete_season.setVisible(False) + + hb_bg = xbmcgui.ControlImage(self.controls_bg.getX() + 10, pos_y + 40, + self.controls_bg.getWidth() - 20, + 2, os.path.join(self.mediapath, 'Controls', 'ScrollBack.png')) + self.addControl(hb_bg) + hb_bg.setVisible(False) + + group = ControlGroup(label_season=label_season, edit_season=edit_season, + label_episode=label_episode, + edit_episode=edit_episode, btn_delete_season=btn_delete_season, hb=hb_bg) + + pos_y += 50 + + if index < 5: + group.set_visible(True) + + self.controls.append(group) + + if len(self.data) > 5: + self.move_scroll() + + except Exception, Ex: + logger.error("HA HABIDO UNA HOSTIA %s" % Ex) + + # def onClick(self, control_id): + # pass + # + # def onFocus(self, control_id): + # pass + + def onControl(self, control): + # logger.debug("%s" % control.getId()) + control_id = control.getId() + + if control_id == ID_BUTTON_OK: + write_data(self.channel, self.show, self.data) + self.close() + if control_id in [ID_BUTTON_CLOSE, ID_BUTTON_CANCEL]: + self.close() + elif control_id == ID_BUTTON_DELETE: + self.close() + borrar(self.channel, self.show) + elif control_id == ID_BUTTON_ADD_SEASON: + # logger.debug("data que enviamos: {}".format(self.data)) + data = add_season(self.data) + if data: + self.data = data + # logger.debug("data que recibimos: {}".format(self.data)) + self.onInit() + + # si hay más de 5 elementos movemos el scroll + if len(self.data) > 5: + self.scroll(len(self.data) - 2, 1) + self.move_scroll() + + elif control_id == ID_BUTTON_INFO: + self.method_info() + else: + for x, grupo in enumerate(self.controls): + if control_id == self.controls[x].btn_delete_season.getId(): + # logger.debug("A data %s" % self.data) + self.removeControls(self.controls[x].list_elements()) + del self.controls[x] + del self.data[x] + # logger.debug("D data %s" % self.data) + self.onInit() + + return + + def onAction(self, action): + # logger.debug("%s" % action.getId()) + # logger.debug("focus %s" % self.getFocusId()) + # Obtenemos el foco + focus = self.getFocusId() + + action = action.getId() + # Flecha izquierda + if action == xbmcgui.ACTION_MOVE_LEFT: + # Si el foco no está en ninguno de los 6 botones inferiores, y esta en un "list" cambiamos el valor + if focus not in [ID_BUTTON_ADD_SEASON, ID_BUTTON_INFO, ID_CHECK_UPDATE_INTERNET, + ID_BUTTON_OK, ID_BUTTON_CANCEL, ID_BUTTON_DELETE]: + + # Localizamos en el listado de controles el control que tiene el focus + # todo mirar tema del cursor en el valor al desplazar lateralmente + for x, linea in enumerate(self.controls): + if focus == linea.edit_season.getId(): + return self.setFocus(self.controls[x].btn_delete_season) + elif focus == linea.edit_episode.getId(): + return self.setFocus(self.controls[x].edit_season) + elif focus == linea.btn_delete_season.getId(): + return self.setFocus(self.controls[x].edit_episode) + + # Si el foco está en alguno de los 6 botones inferiores, movemos al siguiente + else: + if focus in [ID_BUTTON_ADD_SEASON, ID_BUTTON_INFO, ID_CHECK_UPDATE_INTERNET]: + if focus == ID_BUTTON_ADD_SEASON: + self.setFocusId(ID_BUTTON_INFO) + # TODO cambiar cuando se habilite la opcion de actualizar por internet + # self.setFocusId(ID_CHECK_UPDATE_INTERNET) + elif focus == ID_BUTTON_INFO: + self.setFocusId(ID_BUTTON_ADD_SEASON) + elif focus == ID_CHECK_UPDATE_INTERNET: + self.setFocusId(ID_BUTTON_INFO) + + elif focus in [ID_BUTTON_OK, ID_BUTTON_CANCEL, ID_BUTTON_DELETE]: + if focus == ID_BUTTON_OK: + self.setFocusId(ID_BUTTON_DELETE) + elif focus == ID_BUTTON_CANCEL: + self.setFocusId(ID_BUTTON_OK) + elif focus == ID_BUTTON_DELETE: + self.setFocusId(ID_BUTTON_CANCEL) + + # Flecha derecha + elif action == xbmcgui.ACTION_MOVE_RIGHT: + # Si el foco no está en ninguno de los 6 botones inferiores, y esta en un "list" cambiamos el valor + if focus not in [ID_BUTTON_ADD_SEASON, ID_BUTTON_INFO, ID_CHECK_UPDATE_INTERNET, + ID_BUTTON_OK, ID_BUTTON_CANCEL, ID_BUTTON_DELETE]: + + # Localizamos en el listado de controles el control que tiene el focus + # todo mirar tema del cursor en el valor al desplazar lateralmente + for x, linea in enumerate(self.controls): + if focus == linea.edit_season.getId(): + return self.setFocus(self.controls[x].edit_episode) + elif focus == linea.edit_episode.getId(): + return self.setFocus(self.controls[x].btn_delete_season) + elif focus == linea.btn_delete_season.getId(): + return self.setFocus(self.controls[x].edit_season) + + # Si el foco está en alguno de los 6 botones inferiores, movemos al siguiente + else: + if focus in [ID_BUTTON_ADD_SEASON, ID_BUTTON_INFO, ID_CHECK_UPDATE_INTERNET]: + if focus == ID_BUTTON_ADD_SEASON: + self.setFocusId(ID_BUTTON_INFO) + if focus == ID_BUTTON_INFO: + self.setFocusId(ID_BUTTON_ADD_SEASON) + # TODO cambiar cuando se habilite la opcion de actualizar por internet + # self.setFocusId(ID_CHECK_UPDATE_INTERNET) + if focus == ID_CHECK_UPDATE_INTERNET: + self.setFocusId(ID_BUTTON_OK) + + elif focus in [ID_BUTTON_OK, ID_BUTTON_CANCEL, ID_BUTTON_DELETE]: + if focus == ID_BUTTON_OK: + self.setFocusId(ID_BUTTON_CANCEL) + if focus == ID_BUTTON_CANCEL: + self.setFocusId(ID_BUTTON_DELETE) + if focus == ID_BUTTON_DELETE: + self.setFocusId(ID_BUTTON_OK) + + # Flecha arriba + elif action == xbmcgui.ACTION_MOVE_UP: + self.move_up(focus) + # Flecha abajo + elif action == xbmcgui.ACTION_MOVE_DOWN: + self.move_down(focus) + # scroll up + elif action == xbmcgui.ACTION_MOUSE_WHEEL_UP: + self.move_up(focus) + # scroll down + elif action == xbmcgui.ACTION_MOUSE_WHEEL_DOWN: + self.move_down(focus) + + # ACTION_PAGE_DOWN = 6 + # ACTION_PAGE_UP = 5 + + # Menú previo o Atrás + elif action in [xbmcgui.ACTION_PREVIOUS_MENU, xbmcgui.ACTION_NAV_BACK]: + self.close() + + def move_down(self, focus): + # logger.debug("focus " + str(focus)) + # Si el foco está en uno de los tres botones medios, bajamos el foco a la otra linea de botones + if focus in [ID_BUTTON_ADD_SEASON, ID_BUTTON_INFO, ID_CHECK_UPDATE_INTERNET]: + if focus == ID_BUTTON_ADD_SEASON: + self.setFocusId(ID_BUTTON_OK) + elif focus == ID_BUTTON_INFO: + self.setFocusId(ID_BUTTON_CANCEL) + elif focus == ID_CHECK_UPDATE_INTERNET: + self.setFocusId(ID_BUTTON_DELETE) + # Si el foco está en uno de los tres botones inferiores, subimos el foco al primer control del listado + elif focus in [ID_BUTTON_OK, ID_BUTTON_CANCEL, ID_BUTTON_DELETE]: + first_visible = 0 + for x, linea in enumerate(self.controls): + if linea.get_visible(): + first_visible = x + break + + if focus == ID_BUTTON_OK: + self.setFocus(self.controls[first_visible].edit_season) + elif focus == ID_BUTTON_CANCEL: + self.setFocus(self.controls[first_visible].edit_episode) + elif focus == ID_BUTTON_DELETE: + self.setFocus(self.controls[first_visible].btn_delete_season) + # nos movemos entre los elementos del listado + else: + # Localizamos en el listado de controles el control que tiene el focus + for x, linea in enumerate(self.controls): + if focus == linea.edit_season.getId(): + if x + 1 < len(self.controls): + if not self.controls[x + 1].get_visible(): + self.scroll(x, 1) + + return self.setFocus(self.controls[x + 1].edit_season) + else: + return self.setFocusId(ID_BUTTON_ADD_SEASON) + elif focus == linea.edit_episode.getId(): + if x + 1 < len(self.controls): + if not self.controls[x + 1].get_visible(): + self.scroll(x, 1) + + return self.setFocus(self.controls[x + 1].edit_episode) + else: + self.setFocusId(ID_BUTTON_INFO) + elif focus == linea.btn_delete_season.getId(): + if x + 1 < len(self.controls): + if not self.controls[x + 1].get_visible(): + self.scroll(x, 1) + + return self.setFocus(self.controls[x + 1].btn_delete_season) + else: + return self.setFocusId(ID_BUTTON_INFO) + # TODO cambiar cuando se habilite la opcion de actualizar por internet + # return self.setFocusId(ID_CHECK_UPDATE_INTERNET) + + def move_up(self, focus): + # Si el foco está en uno de los tres botones medios, subimos el foco al último control del listado + if focus in [ID_BUTTON_ADD_SEASON, ID_BUTTON_INFO, ID_CHECK_UPDATE_INTERNET]: + last_visible = 0 + for x, linea in reversed(list(enumerate(self.controls))): + if linea.get_visible(): + last_visible = x + break + + if focus == ID_BUTTON_ADD_SEASON: + self.setFocus(self.controls[last_visible].edit_season) + elif focus == ID_BUTTON_INFO: + self.setFocus(self.controls[last_visible].edit_episode) + elif focus == ID_CHECK_UPDATE_INTERNET: + self.setFocus(self.controls[last_visible].btn_delete_season) + # Si el foco está en uno de los tres botones inferiores, subimos el foco a la otra linea de botones + elif focus in [ID_BUTTON_OK, ID_BUTTON_CANCEL, ID_BUTTON_DELETE]: + if focus == ID_BUTTON_OK: + self.setFocusId(ID_BUTTON_ADD_SEASON) + elif focus == ID_BUTTON_CANCEL: + self.setFocusId(ID_BUTTON_INFO) + elif focus == ID_BUTTON_DELETE: + self.setFocusId(ID_BUTTON_INFO) + # TODO cambiar cuando se habilite la opcion de actualizar por internet + # self.setFocusId(ID_CHECK_UPDATE_INTERNET) + # nos movemos entre los elementos del listado + else: + # Localizamos en el listado de controles el control que tiene el focus + for x, linea in enumerate(self.controls): + if focus == linea.edit_season.getId(): + if x > 0: + if not self.controls[x - 1].get_visible(): + self.scroll(x, -1) + + return self.setFocus(self.controls[x - 1].edit_season) + else: + return self.setFocusId(ID_BUTTON_OK) + elif focus == linea.edit_episode.getId(): + if x > 0: + if not self.controls[x - 1].get_visible(): + self.scroll(x, -1) + + return self.setFocus(self.controls[x - 1].edit_episode) + else: + self.setFocusId(ID_BUTTON_CANCEL) + elif focus == linea.btn_delete_season.getId(): + if x > 0: + if not self.controls[x - 1].get_visible(): + self.scroll(x, -1) + + return self.setFocus(self.controls[x - 1].btn_delete_season) + else: + return self.setFocusId(ID_BUTTON_DELETE) + # TODO cambiar cuando se habilite la opcion de actualizar por internet + # return self.setFocusId(ID_CHECK_UPDATE_INTERNET) + + def scroll(self, position, movement): + try: + for index, group in enumerate(self.controls): + # ponemos todos los elementos como no visibles + group.set_visible(False) + + if movement > 0: + pos_fin = position + movement + 1 + pos_inicio = pos_fin - 5 + else: + pos_inicio = position + movement + pos_fin = pos_inicio + 5 + + # logger.debug("position {}, movement {}, pos_inicio{}, pos_fin{}, self.data.length{}". + # format(position, movement, pos_inicio, pos_fin, len(self.data))) + pos_y = self.controls_bg.getY() + 10 + for i in range(pos_inicio, pos_fin): + pos_x = self.controls_bg.getX() + 15 + + self.controls[i].label_season.setPosition(pos_x, pos_y + 3) + + pos_x += self.controls[i].label_season.getWidth() + 5 + self.controls[i].edit_season.setPosition(pos_x, pos_y - 2) + + pos_x += self.controls[i].edit_season.getWidth() + 60 + self.controls[i].label_episode.setPosition(pos_x, pos_y + 3) + + pos_x += self.controls[i].label_episode.getWidth() + 5 + self.controls[i].edit_episode.setPosition(pos_x, pos_y - 2) + + self.controls[i].btn_delete_season.setPosition( + self.controls_bg.getX() + self.controls_bg.getWidth() - + self.controls[i].btn_delete_season.getWidth() - 14, + pos_y) + + self.controls[i].hb.setPosition(self.controls_bg.getX() + 10, pos_y + 40) + + pos_y += 50 + + # logger.debug("ponemos como True %s" % i) + self.controls[i].set_visible(True) + + self.move_scroll() + + except Exception, Ex: + logger.error("HA HABIDO UNA HOSTIA %s" % Ex) + + def move_scroll(self): + visible_controls = [group for group in self.controls if group.get_visible() == True] + hidden_controls = [group for group in self.controls if group.get_visible() == False] + scroll_position = self.controls.index(visible_controls[0]) + scrollbar_height = self.scroll_bg.getHeight() - (len(hidden_controls) * 10) + scrollbar_y = self.scroll_bg.getPosition()[1] + (scroll_position * 10) + self.scroll2_bg.setPosition(self.scroll_bg.getPosition()[0], scrollbar_y) + self.scroll2_bg.setHeight(scrollbar_height) + + @staticmethod + def method_info(): + title = config.get_localized_string(60348) + # text = "La primera temporada que se añade siempre empieza en \"0\" episodios, la segunda temporada que se " + # text += "añade empieza en el número total de episodios de la primera temporada, la tercera temporada será " + # text += "la suma de los episodios de las temporadas previas y así sucesivamente.\n" + # text += "[COLOR blue]\nEjemplo de serie divida en varias temporadas:\n" + # text += "\nFairy Tail:\n" + # text += " - SEASON 1: EPISODE 48 --> [season 1, episode: 0]\n" + # text += " - SEASON 2: EPISODE 48 --> [season 2, episode: 48]\n" + # text += " - SEASON 3: EPISODE 54 --> [season 3, episode: 96 ([48=season2] + [48=season1])]\n" + # text += " - SEASON 4: EPISODE 175 --> [season 4: episode: 150 ([54=season3] + [48=season2] + [48=season3" \ + # "])][/COLOR]\n" + # text += "[COLOR green]\nEjemplo de serie que continua en la temporada de la original:\n" + # text += "\nFate/Zero 2nd Season:\n" + # text += " - SEASON 1: EPISODE 12 --> [season 1, episode: 13][/COLOR]\n" + + # text += "[COLOR blue]\nEjemplo de serie que es la segunda temporada de la original:\n" + # text += "\nFate/kaleid liner Prisma☆Illya 2wei!:\n" + # text += " - SEASON 1: EPISODE 12 --> [season 2, episode: 0][/COLOR]\n" + text = config.get_localized_string(70602) + + return TextBox("DialogTextViewer.xml", os.getcwd(), "Default", title=title, text=text) + + + class ControlGroup: + """ + conjunto de controles, son los elementos que se muestra por línea de una lista. + """ + + def __init__(self, label_season, edit_season, label_episode, edit_episode, btn_delete_season, hb): + self.visible = False + self.label_season = label_season + self.edit_season = edit_season + self.label_episode = label_episode + self.edit_episode = edit_episode + self.btn_delete_season = btn_delete_season + self.hb = hb + + def list_elements(self): + return [self.label_season, self.edit_season, self.label_episode, self.edit_episode, self.btn_delete_season, + self.hb] + + def get_visible(self): + return self.visible + + def set_visible(self, visible): + self.visible = visible + self.label_season.setVisible(visible) + self.edit_season.setVisible(visible) + self.label_episode.setVisible(visible) + self.edit_episode.setVisible(visible) + self.btn_delete_season.setVisible(visible) + self.hb.setVisible(visible) + + + class TextBox(xbmcgui.WindowXMLDialog): + """ Create a skinned textbox window """ + + def __init__(self, *args, **kwargs): + self.title = kwargs.get('title') + self.text = kwargs.get('text') + self.doModal() + + def onInit(self): + try: + self.getControl(5).setText(self.text) + self.getControl(1).setLabel(self.title) + except: + pass + + def onClick(self, control_id): + pass + + def onFocus(self, control_id): + pass + + def onAction(self, action): + self.close() + + # TODO mirar retro-compatiblidad + # class ControlEdit(xbmcgui.ControlButton): + # def __new__(self, *args, **kwargs): + # del kwargs["isPassword"] + # del kwargs["window"] + # args = list(args) + # return xbmcgui.ControlButton.__new__(self, *args, **kwargs) + # + # def __init__(self, *args, **kwargs): + # self.isPassword = kwargs["isPassword"] + # self.window = kwargs["window"] + # self.label = "" + # self.text = "" + # self.textControl = xbmcgui.ControlLabel(self.getX(), self.getY(), self.getWidth(), self.getHeight(), + # self.text, + # font=kwargs["font"], textColor=kwargs["textColor"], alignment=4 | 1) + # self.window.addControl(self.textControl) + # + # def setLabel(self, val): + # self.label = val + # xbmcgui.ControlButton.setLabel(self, val) + # + # def getX(self): + # return xbmcgui.ControlButton.getPosition(self)[0] + # + # def getY(self): + # return xbmcgui.ControlButton.getPosition(self)[1] + # + # def setEnabled(self, e): + # xbmcgui.ControlButton.setEnabled(self, e) + # self.textControl.setEnabled(e) + # + # def setWidth(self, w): + # xbmcgui.ControlButton.setWidth(self, w) + # self.textControl.setWidth(w / 2) + # + # def setHeight(self, w): + # xbmcgui.ControlButton.setHeight(self, w) + # self.textControl.setHeight(w) + # + # def setPosition(self, x, y): + # xbmcgui.ControlButton.setPosition(self, x, y) + # self.textControl.setPosition(x + self.getWidth() / 2, y) + # + # def setText(self, text): + # self.text = text + # if self.isPassword: + # self.textControl.setLabel("*" * len(self.text)) + # else: + # self.textControl.setLabel(self.text) + # + # def getText(self): + # return self.text + # + # + # if not hasattr(xbmcgui, "ControlEdit"): + # xbmcgui.ControlEdit = ControlEdit diff --git a/channels/trailertools.py b/specials/trailertools.py similarity index 100% rename from channels/trailertools.py rename to specials/trailertools.py