def __init__(self, util, listeners, voice_assistant): """ Initializer :param util: utility object :param listeners: listeners :param voice_assistant: voice assistant """ self.util = util self.config = util.config self.listeners = listeners self.listeners[KEY_LIST] = self.set_list self.factory = Factory(util) dbutil = util.get_db_util() self.selector = Selector(dbutil) self.bounding_box = util.screen_rect layout = BorderLayout(self.bounding_box) layout.set_percent_constraints(PERCENT_TOP_HEIGHT, PERCENT_BOTTOM_HEIGHT, 0, 0) MenuScreen.__init__(self, util, listeners, ROWS, COLUMNS, voice_assistant, [ROWS, COLUMNS], self.turn_page, page_in_title=False, show_loading=False) m = self.factory.create_collection_menu_button self.topic_menu = MultiPageMenu(util, self.next_page, self.previous_page, self.set_title, self.reset_title, self.go_to_page, m, ROWS, COLUMNS, None, (0, 0, 0), self.menu_layout, align=ALIGN_LEFT) self.set_menu(self.topic_menu) self.navigator = TopicNavigator(self.util, self.layout.BOTTOM, listeners) self.components.append(self.navigator) self.current_topic = None self.current_item = None self.current_page_items = None self.first_item = None self.last_item = None self.collection_topic = None self.previous_page = 1 self.search_string = None self.source = None self.mode = KEY_LIST self.animated_title = True
def __init__(self, util, listeners, go_book_by_genre, genres, base_url, voice_assistant, d): self.util = util self.go_book_by_genre = go_book_by_genre self.config = util.config self.genres_list = genres self.base_url = base_url self.factory = Factory(util) MenuScreen.__init__(self, util, listeners, MENU_ROWS, MENU_COLUMNS, voice_assistant, d, self.turn_page) self.total_pages = math.ceil(len(genres) / PAGE_SIZE) self.title = self.config[LABELS][KEY_CHOOSE_GENRE] m = self.create_book_genre_menu_button font_size = int(((self.menu_layout.h / MENU_ROWS) / 100) * self.config[FONT_HEIGHT_PERCENT]) self.genre_menu = MultiPageMenu(util, self.next_page, self.previous_page, self.set_title, self.reset_title, self.go_to_page, m, MENU_ROWS, MENU_COLUMNS, None, (0, 0, 0, 0), self.menu_layout, font_size=font_size) self.set_menu(self.genre_menu) self.navigator = BookNavigator(util, self.layout.BOTTOM, listeners, d[4]) self.add_component(self.navigator) self.turn_page()
def __init__(self, util, listeners, ch, f, go_author, parser, base_url, voice_assistant, d): """ Initializer :param util: utility object :param listeners: screen listeners :param ch: selected character :param f: selected filter :param go_authors: callback :param parser: authors parser :param base_url: url :param d: dictionary with menu button flags """ self.util = util self.factory = Factory(util) self.base_url = base_url self.config = util.config self.parser = parser self.current_author_char = ch self.current_author_filter = f self.go_author = go_author self.author_cache = {} self.title = self.config[LABELS][KEY_AUTHORS] MenuScreen.__init__(self, util, listeners, MENU_ROWS, MENU_COLUMNS, voice_assistant, d, self.turn_page) m = self.factory.create_book_author_menu_button self.authors_menu = MultiPageMenu(util, self.next_page, self.previous_page, self.set_title, self.reset_title, self.go_to_page, m, MENU_ROWS, MENU_COLUMNS, None, (0, 0, 0), self.menu_layout) self.set_menu(self.authors_menu)
def __init__(self, util, listeners, voice_assistant): """ Initializer :param util: utility object :param listeners: listeners :param voice_assistant: voice assistant """ self.util = util self.config = util.config self.listeners = listeners self.factory = Factory(util) self.go_home = listeners[KEY_HOME] self.go_file_playback = listeners[KEY_PLAY_COLLECTION] dbutil = util.get_db_util() self.selector = Selector(dbutil) self.bounding_box = util.screen_rect layout = BorderLayout(self.bounding_box) layout.set_percent_constraints(PERCENT_TOP_HEIGHT, PERCENT_BOTTOM_HEIGHT, 0, 0) MenuScreen.__init__(self, util, listeners, ROWS, COLUMNS, voice_assistant, [ROWS, COLUMNS], self.turn_page, page_in_title=False, show_loading=False) m = self.factory.create_collection_menu_button font_size = int(((self.menu_layout.h / ROWS) / 100) * FONT_HEIGHT) self.collection_list_menu = MultiPageMenu(util, self.next_page, self.previous_page, self.set_title, self.reset_title, self.go_to_page, m, ROWS, COLUMNS, None, (0, 0, 0, 0), self.menu_layout, align=ALIGN_LEFT, font_size=font_size) self.set_menu(self.collection_list_menu) self.navigator = TopicDetailNavigator(self.util, self.layout.BOTTOM, listeners) self.add_component(self.navigator) self.current_item = None self.current_page_items = None self.first_item = None self.last_item = None self.collection_topic = None self.selection = None self.prev_page = 1 self.animated_title = True
def __init__(self, util, next_page, previous_page, set_title, reset_title, go_to_page, play_track, bgr=None, bounding_box=None): """ Initializer :param util: utility object :param next_page: next page callback :param previous_page: previous page callback :param set_title: set title callback :param reset_title: reset title callback :param go_to_page: go to page callback :param play_track: play track callback :param bgr: menu background :param bounding_box: bounding box """ self.factory = Factory(util) self.util = util self.next_page = next_page self.previous_page = previous_page self.bb = bounding_box m = self.factory.create_track_menu_button MultiPageMenu.__init__(self, util, next_page, previous_page, set_title, reset_title, go_to_page, m, TRACK_ROWS, TRACK_COLUMNS, None, bgr, bounding_box) self.config = util.config self.play_track = play_track self.tracks = None
def __init__(self, util, listeners, voice_assistant): """ Initializer :param util: utility object :param listeners: listeners :param voice_assistant: voice assistant """ self.util = util self.config = util.config self.listeners = listeners self.factory = Factory(util) self.podcasts_util = util.get_podcasts_util() self.bounding_box = util.screen_rect layout = BorderLayout(self.bounding_box) layout.set_percent_constraints(PERCENT_TOP_HEIGHT, PERCENT_BOTTOM_HEIGHT, 0, 0) d = [MENU_ROWS_PODCASTS, MENU_COLUMNS_PODCASTS] MenuScreen.__init__(self, util, listeners, MENU_ROWS_PODCASTS, MENU_COLUMNS_PODCASTS, voice_assistant, d, self.turn_page, page_in_title=False, show_loading=True) self.title = self.config[LABELS][PODCASTS] m = self.factory.create_podcast_menu_button self.podcasts_menu = MultiPageMenu(util, self.next_page, self.previous_page, self.set_title, self.reset_title, self.go_to_page, m, MENU_ROWS_PODCASTS, MENU_COLUMNS_PODCASTS, None, (0, 0, 0), self.menu_layout, align=ALIGN_CENTER) self.set_menu(self.podcasts_menu) self.navigator = PodcastNavigator( self.util, self.layout.BOTTOM, listeners, self.config[COLORS][COLOR_DARK_LIGHT], PAGE_SIZE_PODCASTS + 1) self.components.append(self.navigator) url = self.config[PODCASTS][PODCAST_URL] if url and len(url) > 0: self.current_page = self.podcasts_util.get_podcast_page( url, PAGE_SIZE_PODCASTS) else: self.current_page = 1 self.animated_title = True
def __init__(self, util, listeners, voice_assistant, state): """ Initializer :param util: utility object :param listeners: file browser listeners :param voice_assistant: voice assistant :param state: button state """ self.util = util self.config = util.config self.podcasts_util = util.get_podcasts_util() self.listeners = listeners self.factory = Factory(util) self.bounding_box = util.screen_rect self.layout = BorderLayout(self.bounding_box) self.layout.set_percent_constraints(PERCENT_TOP_HEIGHT, PERCENT_BOTTOM_HEIGHT, 0, 0) d = [MENU_ROWS_EPISODES, MENU_COLUMNS_EPISODES] MenuScreen.__init__(self, util, listeners, MENU_ROWS_EPISODES, MENU_COLUMNS_EPISODES, voice_assistant, d, self.turn_page, page_in_title=False) if hasattr(state, "podcast_url"): podcast_url = state.podcast_url self.title = self.podcasts_util.summary_cache[podcast_url].name else: self.title = state.name m = self.factory.create_episode_menu_button self.episodes_menu = MultiPageMenu(util, self.next_page, self.previous_page, self.set_title, self.reset_title, self.go_to_page, m, MENU_ROWS_EPISODES, MENU_COLUMNS_EPISODES, None, (0, 0, 0), self.menu_layout, align=ALIGN_MIDDLE) self.set_menu(self.episodes_menu) self.total_pages = PAGE_SIZE_EPISODES * 2 self.episodes = [] self.navigator = EpisodeNavigator( self.util, self.layout.BOTTOM, listeners, self.config[COLORS][COLOR_DARK_LIGHT], self.total_pages) self.components.append(self.navigator) self.current_page = 1 self.save_episode_listeners = []
def __init__(self, util, listeners, voice_assistant): self.util = util self.config = util.config self.groups_list = self.util.get_stations_folders() self.factory = Factory(util) d = [MENU_ROWS, MENU_COLUMNS] MenuScreen.__init__(self, util, listeners, MENU_ROWS, MENU_COLUMNS, voice_assistant, d, self.turn_page, page_in_title=False) self.total_pages = math.ceil(len(self.groups_list) / PAGE_SIZE) self.title = util.get_stations_top_folder() m = self.create_genre_menu_button label_area = ( (self.menu_layout.h / MENU_ROWS) / 100) * (100 - ICON_AREA) font_size = int((label_area / 100) * FONT_HEIGHT) self.navigator = RadioGroupNavigator(self.util, self.layout.BOTTOM, listeners, self.total_pages) self.add_navigator(self.navigator) self.player_button = self.navigator.get_button_by_name(KEY_PLAYER) if self.total_pages > 1: self.left_button = self.navigator.get_button_by_name(KEY_PAGE_DOWN) self.right_button = self.navigator.get_button_by_name(KEY_PAGE_UP) self.groups_menu = MultiPageMenu(util, self.next_page, self.previous_page, self.set_title, self.reset_title, self.go_to_page, m, MENU_ROWS, MENU_COLUMNS, None, (0, 0, 0, 0), self.menu_layout, align=ALIGN_CENTER, font_size=font_size) self.groups_menu.add_listener(listeners[KEY_GENRE]) self.set_menu(self.groups_menu) current_name = self.get_current_group_name() if current_name == None: self.current_page = 1 else: try: current_group_index = self.groups_list.index(current_name) self.current_page = int(current_group_index / PAGE_SIZE) + 1 except: current_group_index = 0 self.turn_page()
def __init__(self, util, listeners, voice_assistant): self.util = util self.config = util.config self.groups_list = self.util.get_stations_folders() self.factory = Factory(util) d = [MENU_ROWS, MENU_COLUMNS] MenuScreen.__init__(self, util, listeners, MENU_ROWS, MENU_COLUMNS, voice_assistant, d, self.turn_page, page_in_title=False) self.total_pages = math.ceil(len(self.groups_list) / PAGE_SIZE) self.title = util.get_stations_top_folder() m = self.factory.create_genre_menu_button self.groups_menu = MultiPageMenu(util, self.next_page, self.previous_page, self.set_title, self.reset_title, self.go_to_page, m, MENU_ROWS, MENU_COLUMNS, None, (0, 0, 0), self.menu_layout, align=ALIGN_CENTER) self.groups_menu.add_listener(listeners[KEY_GENRE]) self.set_menu(self.groups_menu) color_dark_light = self.config[COLORS][COLOR_DARK_LIGHT] self.navigator = RadioGroupNavigator(self.util, self.layout.BOTTOM, listeners, color_dark_light, self.total_pages) self.components.append(self.navigator) current_name = self.get_current_group_name() if current_name == None: self.current_page = 1 else: try: current_group_index = self.groups_list.index(current_name) self.current_page = int(current_group_index / PAGE_SIZE) + 1 except: current_group_index = 0 self.turn_page()
class BookGenre(MenuScreen): """ Bokk genre screen """ def __init__(self, util, listeners, go_book_by_genre, genres, base_url, voice_assistant, d): self.util = util self.go_book_by_genre = go_book_by_genre self.config = util.config self.genres_list = genres self.base_url = base_url self.factory = Factory(util) MenuScreen.__init__(self, util, listeners, MENU_ROWS, MENU_COLUMNS, voice_assistant, d, self.turn_page) self.total_pages = math.ceil(len(genres) / PAGE_SIZE) self.title = self.config[LABELS][KEY_CHOOSE_GENRE] m = self.factory.create_book_genre_menu_button self.genre_menu = MultiPageMenu(util, self.next_page, self.previous_page, self.set_title, self.reset_title, self.go_to_page, m, MENU_ROWS, MENU_COLUMNS, None, (0, 0, 0), self.menu_layout) self.set_menu(self.genre_menu) self.turn_page() def turn_page(self): """ Turn book genre page """ start = (self.current_page - 1) * PAGE_SIZE end = self.current_page * PAGE_SIZE page = self.genres_list[start:end] self.genres_dict = self.factory.create_book_genre_items( page, self.base_url) self.genre_menu.set_items(self.genres_dict, 0, self.go_book_by_genre, False) self.genre_menu.align_labels(ALIGN_LEFT) self.genre_menu.select_by_index(0) self.genre_menu.clean_draw_update() self.navigator.left_button.change_label(str(self.current_page - 1)) self.navigator.right_button.change_label( str(self.total_pages - self.current_page)) self.set_title(self.current_page) def add_screen_observers(self, update_observer, redraw_observer): """ Add screen observers :param update_observer: observer for updating the screen :param redraw_observer: observer to redraw the whole screen """ self.navigator.add_observers(update_observer, redraw_observer) self.genre_menu.add_menu_observers(update_observer, redraw_observer, release=False)
def __init__(self, util, listeners, ch, f, go_author, parser, base_url, voice_assistant, d): """ Initializer :param util: utility object :param listeners: screen listeners :param ch: selected character :param f: selected filter :param go_authors: callback :param parser: authors parser :param base_url: url :param d: dictionary with menu button flags """ self.util = util self.factory = Factory(util) self.base_url = base_url self.config = util.config self.parser = parser self.current_author_char = ch self.current_author_filter = f self.go_author = go_author self.author_cache = {} self.title = self.config[LABELS][KEY_AUTHORS] MenuScreen.__init__(self, util, listeners, MENU_ROWS, MENU_COLUMNS, voice_assistant, d, self.turn_page) m = self.create_book_author_menu_button self.navigator = BookNavigator(util, self.layout.BOTTOM, listeners, d[4]) self.back_button = self.navigator.get_button_by_name(KEY_BACK) self.left_button = self.navigator.get_button_by_name(KEY_PAGE_DOWN) self.right_button = self.navigator.get_button_by_name(KEY_PAGE_UP) self.add_navigator(self.navigator) font_size = int(((self.menu_layout.h / MENU_ROWS) / 100) * self.config[FONT_HEIGHT_PERCENT]) self.authors_menu = MultiPageMenu(util, self.next_page, self.previous_page, self.set_title, self.reset_title, self.go_to_page, m, MENU_ROWS, MENU_COLUMNS, None, (0, 0, 0), self.menu_layout, font_size=font_size) self.set_menu(self.authors_menu)
def __init__(self, util, listeners, voice_assistant): """ Initializer :param util: utility object :param listeners: listeners :param voice_assistant: voice assistant """ self.util = util self.config = util.config self.listeners = listeners self.factory = Factory(util) self.go_home = listeners[KEY_HOME] self.go_keyboard = listeners[KEY_KEYBOARD_KEY] self.keyboard_callback = listeners[KEY_CALLBACK] self.wifi_selection_listeners = [] self.wifi_util = WiFiUtil(util) self.bounding_box = util.screen_rect layout = BorderLayout(self.bounding_box) layout.set_percent_constraints(PERCENT_TOP_HEIGHT, PERCENT_BOTTOM_HEIGHT, 0, 0) d = [MENU_ROWS_WIFI, MENU_COLUMNS_WIFI] MenuScreen.__init__(self, util, listeners, MENU_ROWS_WIFI, MENU_COLUMNS_WIFI, voice_assistant, d, self.turn_page, page_in_title=False, show_loading=False) self.title = self.config[LABELS]["select.wifi"] self.set_title(1) m = self.factory.create_wifi_menu_button self.wifi_menu = MultiPageMenu(util, self.next_page, self.previous_page, self.set_title, self.reset_title, self.go_to_page, m, MENU_ROWS_WIFI, MENU_COLUMNS_WIFI, None, (0, 0, 0), self.menu_layout, align=ALIGN_MIDDLE) self.set_menu(self.wifi_menu) listeners[KEY_REFRESH] = self.set_current listeners[KEY_SORT] = self.sort_abc self.navigator = WiFiNavigator(self.util, self.layout.BOTTOM, listeners, PAGE_SIZE_WIFI + 1) self.components.append(self.navigator) self.original_networks = None self.networks = None self.sort_direction = False self.current_network = None
def __init__(self, util, listeners, go_book_by_genre, genres, base_url, voice_assistant, d): self.util = util self.go_book_by_genre = go_book_by_genre self.config = util.config self.genres_list = genres self.base_url = base_url self.factory = Factory(util) MenuScreen.__init__(self, util, listeners, MENU_ROWS, MENU_COLUMNS, voice_assistant, d, self.turn_page) self.total_pages = math.ceil(len(genres) / PAGE_SIZE) self.title = self.config[LABELS][KEY_CHOOSE_GENRE] m = self.factory.create_book_genre_menu_button self.genre_menu = MultiPageMenu(util, self.next_page, self.previous_page, self.set_title, self.reset_title, self.go_to_page, m, MENU_ROWS, MENU_COLUMNS, None, (0, 0, 0), self.menu_layout) self.set_menu(self.genre_menu) self.turn_page()
def __init__(self, util, next_page, previous_page, set_title, reset_title, go_to_page, callback, rows, columns, menu_button_layout, bounding_box=None): """ Initializer :param util: utility object :param next_page: next page callback :param previous_page: previous page callback :param set_title: set title callback :param reset_title: reset title callback :param go_to_page: go to page callback :param callback: :param rows: menu rows :param columns: menu columns :param menu_button_layout: button layout :param bounding_box: bounding box """ self.factory = Factory(util) self.util = util self.callback = callback self.config = self.util.config m = self.create_book_menu_button self.bounding_box = bounding_box self.menu_button_layout = menu_button_layout MultiPageMenu.__init__(self, util, next_page, previous_page, set_title, reset_title, go_to_page, m, rows, columns, menu_button_layout, None, bounding_box, align=ALIGN_CENTER) self.browsing_history = {} self.left_number_listeners = [] self.right_number_listeners = [] self.change_folder_listeners = [] self.play_file_listeners = [] self.playlist_size_listeners = [] self.menu_navigation_listeners = [] self.page_turned = False self.separator = os.sep self.selected_index = 0 self.empty_state = State()
class PodcastEpisodesScreen(MenuScreen): """ Podcast Episodes Screen """ def __init__(self, util, listeners, voice_assistant, state): """ Initializer :param util: utility object :param listeners: file browser listeners :param voice_assistant: voice assistant :param state: button state """ self.util = util self.config = util.config self.podcasts_util = util.get_podcasts_util() self.listeners = listeners self.factory = Factory(util) self.bounding_box = util.screen_rect self.layout = BorderLayout(self.bounding_box) self.layout.set_percent_constraints(PERCENT_TOP_HEIGHT, PERCENT_BOTTOM_HEIGHT, 0, 0) d = [MENU_ROWS_EPISODES, MENU_COLUMNS_EPISODES] MenuScreen.__init__(self, util, listeners, MENU_ROWS_EPISODES, MENU_COLUMNS_EPISODES, voice_assistant, d, self.turn_page, page_in_title=False) if hasattr(state, "podcast_url"): podcast_url = state.podcast_url self.title = self.podcasts_util.summary_cache[podcast_url].name else: self.title = state.name m = self.factory.create_episode_menu_button self.episodes_menu = MultiPageMenu(util, self.next_page, self.previous_page, self.set_title, self.reset_title, self.go_to_page, m, MENU_ROWS_EPISODES, MENU_COLUMNS_EPISODES, None, (0, 0, 0), self.menu_layout, align=ALIGN_MIDDLE) self.set_menu(self.episodes_menu) self.total_pages = PAGE_SIZE_EPISODES * 2 self.episodes = [] self.navigator = EpisodeNavigator( self.util, self.layout.BOTTOM, listeners, self.config[COLORS][COLOR_DARK_LIGHT], self.total_pages) self.components.append(self.navigator) self.current_page = 1 self.save_episode_listeners = [] def set_current(self, state): """ Set current state :param state: button state """ if not self.util.connected_to_internet and len( self.episodes) == 0 and not hasattr(state, "url"): return if state.name == KEY_BACK or (getattr(state, "source", None) == FILE_BUTTON and len(self.episodes) != 0): self.episodes_menu.clean_draw_update() return if getattr(state, "podcast_url", None) != None: self.episodes = self.podcasts_util.get_episodes(state.podcast_url) if len(self.episodes) != 0: self.total_pages = math.ceil( len(self.episodes) / PAGE_SIZE_EPISODES) self.turn_page(state) return self.set_loading(self.title) if state.name != self.title or len(self.episodes) == 0: self.title = state.name if self.util.connected_to_internet: self.episodes = self.podcasts_util.get_episodes(state.url) else: self.episodes = self.podcasts_util.get_episodes_from_disk( state.url) self.total_pages = math.ceil(len(self.episodes) / PAGE_SIZE_EPISODES) self.turn_page(state) self.reset_loading() def turn_page(self, state=None): """ Turn screen page :param state: button state """ filelist = Page(self.episodes, MENU_ROWS_EPISODES, MENU_COLUMNS_EPISODES) if state == None: filelist.current_page_index = self.current_page - 1 index = filelist.current_page_index * PAGE_SIZE_EPISODES else: if getattr(state, "status", None) == STATUS_LOADED: if hasattr(state, "original_url") and len( state.original_url.strip()) > 0: filelist.set_current_item_by_url(state.original_url) else: filelist.set_current_item_by_file_name(state.file_name) else: filelist.set_current_item_by_url(state.url) index = filelist.current_item_index self.current_page = filelist.current_page_index + 1 page = filelist.get_current_page() d = self.episodes_menu.make_dict(page) self.episodes_menu.set_items(d, filelist.current_page_index, self.select_episode, False) self.set_title(self.current_page) self.episodes_menu.unselect() self.episodes_menu.select_by_index(index) self.navigator.left_button.change_label( str(filelist.get_left_items_number())) self.navigator.right_button.change_label( str(filelist.get_right_items_number())) self.episodes_menu.clean_draw_update() if hasattr(self, "update_observer"): self.episodes_menu.add_menu_observers(self.update_observer, self.redraw_observer) def select_episode(self, state): """ Select podacst episode :param state: button state """ if getattr(state, "long_press", None) == True: if state.status == STATUS_LOADED: self.podcasts_util.delete_episode(state) if not self.util.connected_to_internet: for i, c in enumerate(self.episodes): if c.name == state.name: del self.episodes[i] break if len(self.episodes) == 0: self.title = " " self.set_title(0) self.turn_page(state) else: state.icon_base = state.event_origin.components[ 1].content = self.podcasts_util.available_icon state.status = STATUS_AVAILABLE elif state.status == STATUS_AVAILABLE: if self.podcasts_util.is_podcast_folder_available(): state.icon_base = state.event_origin.components[ 1].content = self.podcasts_util.loading_icon state.status = STATUS_LOADING self.add_save_episode_listener(state) self.podcasts_util.save_episode( state, self.notify_save_episode_listeners) self.clean_draw_update() else: podcast_player = self.listeners[KEY_PLAYER] podcast_player(state) def add_save_episode_listener(self, listener): """ Add save episode listener :param listener: event listener """ if listener not in self.save_episode_listeners: self.save_episode_listeners.append(listener) def notify_save_episode_listeners(self): """ Notify all save episode listeners """ for index, listener in enumerate(self.save_episode_listeners): listener.icon_base = listener.event_origin.components[ 1].content = self.podcasts_util.loaded_icon listener.status = STATUS_LOADED self.clean_draw_update() if hasattr(self, "redraw_observer"): self.redraw_observer() del self.save_episode_listeners[index] def add_screen_observers(self, update_observer, redraw_observer): """ Add screen observers :param update_observer: observer for updating the screen :param redraw_observer: observer to redraw the whole screen """ MenuScreen.add_screen_observers(self, update_observer, redraw_observer) self.update_observer = update_observer self.redraw_observer = redraw_observer self.add_loading_listener(redraw_observer) self.navigator.add_observers(self.update_observer, self.redraw_observer)
def __init__(self, util, listeners, voice_assistant): """ Initializer :param util: utility object :param listeners: listeners :param voice_assistant: voice assistant """ self.util = util self.config = util.config self.listeners = listeners self.factory = Factory(util) self.go_home = listeners[KEY_HOME] self.go_network = listeners[KEY_NETWORK] self.go_player = listeners[KEY_PLAYER] self.wifi_selection_listeners = [] self.bluetooth_util = self.util.get_bluetooth_util() self.bounding_box = util.screen_rect layout = BorderLayout(self.bounding_box) layout.set_percent_constraints(PERCENT_TOP_HEIGHT, PERCENT_BOTTOM_HEIGHT, 0, 0) d = [MENU_ROWS_BLUETOOTH, MENU_COLUMNS_BLUETOOTH] MenuScreen.__init__(self, util, listeners, MENU_ROWS_BLUETOOTH, MENU_COLUMNS_BLUETOOTH, voice_assistant, d, self.turn_page, page_in_title=False, show_loading=False) self.title = self.config[LABELS]["select.bluetooth.device"] self.set_title(1) m = self.factory.create_wifi_menu_button self.bluetooth_menu = MultiPageMenu(util, self.next_page, self.previous_page, self.set_title, self.reset_title, self.go_to_page, m, MENU_ROWS_BLUETOOTH, MENU_COLUMNS_BLUETOOTH, None, (0, 0, 0), self.menu_layout, align=ALIGN_LEFT) self.set_menu(self.bluetooth_menu) listeners[KEY_HOME] = self.before_home listeners[KEY_NETWORK] = self.before_network listeners[KEY_PLAYER] = self.before_player listeners[KEY_REFRESH] = self.set_current self.navigator = BluetoothNavigator(self.util, self.layout.BOTTOM, listeners, PAGE_SIZE_BLUETOOTH + 1) self.components.append(self.navigator) self.devices = None self.networks = None self.sort_direction = False self.current_device = None
class BluetoothScreen(MenuScreen): """ Bluetooth Screen """ def __init__(self, util, listeners, voice_assistant): """ Initializer :param util: utility object :param listeners: listeners :param voice_assistant: voice assistant """ self.util = util self.config = util.config self.listeners = listeners self.factory = Factory(util) self.go_home = listeners[KEY_HOME] self.go_network = listeners[KEY_NETWORK] self.go_player = listeners[KEY_PLAYER] self.wifi_selection_listeners = [] self.bluetooth_util = self.util.get_bluetooth_util() self.bounding_box = util.screen_rect layout = BorderLayout(self.bounding_box) layout.set_percent_constraints(PERCENT_TOP_HEIGHT, PERCENT_BOTTOM_HEIGHT, 0, 0) d = [MENU_ROWS_BLUETOOTH, MENU_COLUMNS_BLUETOOTH] MenuScreen.__init__(self, util, listeners, MENU_ROWS_BLUETOOTH, MENU_COLUMNS_BLUETOOTH, voice_assistant, d, self.turn_page, page_in_title=False, show_loading=False) self.title = self.config[LABELS]["select.bluetooth.device"] self.set_title(1) m = self.factory.create_wifi_menu_button self.bluetooth_menu = MultiPageMenu(util, self.next_page, self.previous_page, self.set_title, self.reset_title, self.go_to_page, m, MENU_ROWS_BLUETOOTH, MENU_COLUMNS_BLUETOOTH, None, (0, 0, 0), self.menu_layout, align=ALIGN_LEFT) self.set_menu(self.bluetooth_menu) listeners[KEY_HOME] = self.before_home listeners[KEY_NETWORK] = self.before_network listeners[KEY_PLAYER] = self.before_player listeners[KEY_REFRESH] = self.set_current self.navigator = BluetoothNavigator(self.util, self.layout.BOTTOM, listeners, PAGE_SIZE_BLUETOOTH + 1) self.components.append(self.navigator) self.devices = None self.networks = None self.sort_direction = False self.current_device = None def set_current(self, state): """ Set current state :param state: button state """ self.set_loading(self.title) self.bluetooth_util.start_scan() self.devices = self.bluetooth_util.get_available_devices() if not self.devices: self.reset_loading() self.clean_draw_update() return self.current_device = self.devices[0] d = self.bluetooth_util.get_connected_device() if d: self.current_device = d self.total_pages = math.ceil(len(self.devices) / PAGE_SIZE_BLUETOOTH) self.reset_loading() self.current_page = self.bluetooth_util.get_page_num( self.current_device, self.devices) self.turn_page() def select_network(self, state=None): """ Select network from menu :param state: button state """ if hasattr(state, "mac_address") and self.bluetooth_util.is_device_connected( state.mac_address): self.before_network(state) return state.source = "bluetooth" self.notify_wifi_selection_listeners(state.name) self.before_network(state) def turn_page(self): """ Turn page """ p = self.bluetooth_util.get_page(self.current_page, self.devices) try: self.bluetooth_menu.set_items(p, 0, self.select_network, False) except Exception as e: logging.debug(e) if len(self.devices) != 0 and self.navigator and self.total_pages > 1: self.navigator.left_button.change_label(str(self.current_page - 1)) self.navigator.right_button.change_label( str(self.total_pages - self.current_page)) self.set_title(self.current_page) self.bluetooth_menu.clean_draw_update() if hasattr(self, "update_observer"): self.bluetooth_menu.add_menu_observers(self.update_observer, self.redraw_observer) self.bluetooth_menu.unselect() for b in self.bluetooth_menu.buttons.values(): if self.current_device["name"] == b.state.name: self.bluetooth_menu.select_by_index(b.state.index) return index = (self.current_page - 1) * PAGE_SIZE_BLUETOOTH self.bluetooth_menu.select_by_index(index) def before_home(self, state): """ Stop bluetooth scanning and go to home screen :param state: button state """ self.bluetooth_util.stop_scan() self.go_home(state) def before_network(self, state): """ Stop bluetooth scanning and go to network screen :param state: button state """ self.bluetooth_util.stop_scan() self.go_network(state) def before_player(self, state): """ Stop bluetooth scanning and go to player screen :param state: button state """ self.bluetooth_util.stop_scan() self.go_player(state) def add_bluetooth_selection_listener(self, listener): """ Add listener :param listener: event listener """ if listener not in self.wifi_selection_listeners: self.wifi_selection_listeners.append(listener) def notify_wifi_selection_listeners(self, selected_wifi): """ Notify all listeners :param selected_wifi: """ for listener in self.wifi_selection_listeners: listener(selected_wifi) def add_screen_observers(self, update_observer, redraw_observer): """ Add screen observers :param update_observer: observer for updating the screen :param redraw_observer: observer to redraw the whole screen """ MenuScreen.add_screen_observers(self, update_observer, redraw_observer) self.update_observer = update_observer self.redraw_observer = redraw_observer self.add_loading_listener(redraw_observer) for b in self.navigator.menu_buttons: self.add_button_observers(b, update_observer, redraw_observer)
class TopicDetailScreen(MenuScreen): """ Topic Detail Screen """ def __init__(self, util, listeners, voice_assistant): """ Initializer :param util: utility object :param listeners: listeners :param voice_assistant: voice assistant """ self.util = util self.config = util.config self.listeners = listeners self.factory = Factory(util) self.go_home = listeners[KEY_HOME] self.go_file_playback = listeners[KEY_PLAY_COLLECTION] dbutil = util.get_db_util() self.selector = Selector(dbutil) self.bounding_box = util.screen_rect layout = BorderLayout(self.bounding_box) layout.set_percent_constraints(PERCENT_TOP_HEIGHT, PERCENT_BOTTOM_HEIGHT, 0, 0) MenuScreen.__init__(self, util, listeners, ROWS, COLUMNS, voice_assistant, [ROWS, COLUMNS], self.turn_page, page_in_title=False, show_loading=False) m = self.factory.create_collection_menu_button self.collection_list_menu = MultiPageMenu(util, self.next_page, self.previous_page, self.set_title, self.reset_title, self.go_to_page, m, ROWS, COLUMNS, None, (0, 0, 0), self.menu_layout, align=ALIGN_LEFT) self.set_menu(self.collection_list_menu) self.navigator = TopicDetailNavigator(self.util, self.layout.BOTTOM, listeners) self.components.append(self.navigator) self.current_item = None self.current_page_items = None self.first_item = None self.last_item = None self.collection_topic = None self.selection = None self.prev_page = 1 self.animated_title = True def set_current(self, state): """ Set current state :param state: button state """ source = getattr(state, KEY_SOURCE, None) if source == KEY_NAVIGATOR or source == KEY_BACK: return if hasattr(state, "collection_topic"): self.collection_topic = getattr(state, "collection_topic", "") if self.current_item and self.current_item[0] == getattr( state, "name", None): return if hasattr(state, "name"): self.selection = getattr(state, "name", "") self.title = self.config[LABELS][ self.collection_topic] + ": " + self.selection self.set_title(1) self.current_page = 1 self.prev_page = 1 self.navigator.left_button.change_label("0") self.navigator.right_button.change_label("0") self.set_loading(self.title) topic = self.get_topic() self.total_pages = self.selector.get_page_count_by_column( topic, self.selection, PAGE_SIZE) if self.total_pages == 0: self.reset_loading() return self.filename = None self.title = None if self.collection_topic == KEY_FILE: self.filename = state.name elif self.collection_topic == TITLE: self.title = state.name self.turn_page() self.reset_loading() def turn_page(self): """ Turn page """ topic = self.get_topic() self.current_page_items = self.selector.get_topic_detail_page( topic, self.selection, self.current_page, self.prev_page, self.first_item, self.last_item, PAGE_SIZE) self.prev_page = self.current_page if not self.current_page_items: self.current_page_items = [] return self.current_item = self.current_page_items[0] self.first_item = self.current_item self.last_item = self.current_page_items[len(self.current_page_items) - 1] p = {} for i, f in enumerate(self.current_page_items): s = State() s.index = i s.folder = f if "\x00" in f: f = f.replace("\x00", "") if "/" in f: parts = f.split("/") if len(parts) > 1: last = parts[len(parts) - 1] if len(last) > 6: f = last else: f = parts[len(parts) - 2] + "/" + last s.name = f s.l_name = s.name if self.filename: s.file_name = self.filename if self.title: s.title = self.title p[str(i)] = s self.collection_list_menu.set_items(p, 0, self.select_item, False) keys = list(p.keys()) if len(keys) != 0 and self.navigator and self.total_pages > 1: self.navigator.left_button.change_label(str(self.current_page - 1)) self.navigator.right_button.change_label( str(self.total_pages - self.current_page)) self.collection_list_menu.clean_draw_update() if hasattr(self, "update_observer"): self.collection_list_menu.add_menu_observers( self.update_observer, self.redraw_observer) self.collection_list_menu.unselect() for i, b in enumerate(self.collection_list_menu.buttons.values()): if self.current_item[0] == b.state.name: self.collection_list_menu.select_by_index(b.state.index) return index = (self.current_page - 1) * PAGE_SIZE self.collection_list_menu.select_by_index(index) def get_topic(self): """ Get topic :return: proper topic name """ topic = self.collection_topic if topic == KEY_AUDIO_FOLDER: topic = FOLDER elif topic == KEY_FILE: topic = FILENAME return topic def select_item(self, s=None): """ Select item from menu :param state: button state """ self.current_item = s.name state = State() state.folder = os.path.join(self.config[COLLECTION][BASE_FOLDER], s.folder[1:]) state.topic = self.collection_topic if state.topic == KEY_FILE: state.file_name = s.file_name elif state.topic == TITLE: state.file_name = self.selector.get_filename_by_title( s.folder, self.title) state.url = os.path.join(state.folder, state.file_name) else: files = self.util.get_audio_files_in_folder(state.folder, False) if files: f = files[0] state.file_name = f.file_name state.url = os.path.join(state.folder, state.file_name) else: state.file_name = None state.url = None state.source = "detail" self.collection_list_menu.select_by_index(s.index) self.go_file_playback(state) def add_screen_observers(self, update_observer, redraw_observer): """ Add screen observers :param update_observer: observer for updating the screen :param redraw_observer: observer to redraw the whole screen """ MenuScreen.add_screen_observers(self, update_observer, redraw_observer) self.update_observer = update_observer self.redraw_observer = redraw_observer self.add_loading_listener(redraw_observer) for b in self.navigator.menu_buttons: self.add_button_observers(b, update_observer, redraw_observer)
class PodcastsScreen(MenuScreen): """ Podcasts Screen """ def __init__(self, util, listeners, voice_assistant): """ Initializer :param util: utility object :param listeners: listeners :param voice_assistant: voice assistant """ self.util = util self.config = util.config self.listeners = listeners self.factory = Factory(util) self.podcasts_util = util.get_podcasts_util() self.bounding_box = util.screen_rect layout = BorderLayout(self.bounding_box) layout.set_percent_constraints(PERCENT_TOP_HEIGHT, PERCENT_BOTTOM_HEIGHT, 0, 0) d = [MENU_ROWS_PODCASTS, MENU_COLUMNS_PODCASTS] MenuScreen.__init__(self, util, listeners, MENU_ROWS_PODCASTS, MENU_COLUMNS_PODCASTS, voice_assistant, d, self.turn_page, page_in_title=False, show_loading=True) self.title = self.config[LABELS][PODCASTS] m = self.create_podcast_menu_button font_size = int( ((self.menu_layout.h / MENU_ROWS_PODCASTS) / 100) * FONT_HEIGHT) self.podcasts_menu = MultiPageMenu(util, self.next_page, self.previous_page, self.set_title, self.reset_title, self.go_to_page, m, MENU_ROWS_PODCASTS, MENU_COLUMNS_PODCASTS, None, (0, 0, 0, 0), self.menu_layout, align=ALIGN_CENTER, font_size=font_size) self.set_menu(self.podcasts_menu) self.navigator = PodcastNavigator(self.util, self.layout.BOTTOM, listeners, PAGE_SIZE_PODCASTS + 1) self.add_component(self.navigator) url = self.config[PODCASTS][PODCAST_URL] if url and len(url) > 0: self.current_page = self.podcasts_util.get_podcast_page( url, PAGE_SIZE_PODCASTS) else: self.current_page = 1 self.animated_title = True def create_podcast_menu_button(self, s, constr, action, scale, font_size): """ Create podcast menu button :param s: button state :param constr: scaling constraints :param action: button event listener :param scale: True - scale images, False - don't scale images :return: genre menu button """ s.bounding_box = constr s.img_x = None s.img_y = None s.auto_update = True s.show_bgr = True s.show_img = True s.show_label = True s.image_location = ICON_LOCATION s.label_location = CENTER s.label_area_percent = 30 s.image_size_percent = ICON_SIZE s.text_color_normal = self.config[COLORS][COLOR_BRIGHT] s.text_color_selected = self.config[COLORS][COLOR_CONTRAST] s.text_color_disabled = self.config[COLORS][COLOR_MEDIUM] s.text_color_current = s.text_color_normal s.scale = scale s.source = None s.v_align = V_ALIGN_TOP s.h_align = H_ALIGN_LEFT s.v_offset = (constr.h / 100) * 5 s.bgr = self.config[BACKGROUND][MENU_BGR_COLOR] s.image_area_percent = ICON_AREA s.fixed_height = font_size button = PodcastButton(self.util, s) button.add_release_listener(action) if not getattr(s, "enabled", True): button.set_enabled(False) elif getattr(s, "icon_base", False) and not getattr(s, "scaled", False): button.components[1].content = s.icon_base button.scaled = scale return button def set_current(self, state): """ Set current state :param state: button state """ if self.util.connected_to_internet: podcast_links_num = len(self.podcasts_util.get_podcasts_links()) else: podcast_links_num = len(self.podcasts_util.load_podcasts()) self.total_pages = math.ceil(podcast_links_num / PAGE_SIZE_PODCASTS) self.set_loading(self.title) self.turn_page() self.reset_loading() def turn_page(self): """ Turn podcasts page """ page = {} if self.util.connected_to_internet: page = self.podcasts_util.get_podcasts(self.current_page, PAGE_SIZE_PODCASTS) if len(list(page.keys())) == 0 or not self.util.connected_to_internet: page = self.podcasts_util.get_podcasts_from_disk( self.current_page, PAGE_SIZE_PODCASTS) self.podcasts_menu.set_items(page, 0, self.listeners[KEY_PODCAST_EPISODES], False) keys = list(page.keys()) if len(keys) != 0: self.podcasts_menu.item_selected(page[keys[0]]) if self.navigator and self.total_pages > 1: self.navigator.left_button.change_label( str(self.current_page - 1)) self.navigator.right_button.change_label( str(self.total_pages - self.current_page)) self.set_title(self.current_page) self.podcasts_menu.clean_draw_update() if hasattr(self, "update_observer"): self.podcasts_menu.add_menu_observers(self.update_observer, self.redraw_observer) self.podcasts_menu.unselect() for i, b in enumerate(self.podcasts_menu.buttons.values()): url = self.config[PODCASTS][PODCAST_URL] if url == b.state.url: self.podcasts_menu.select_by_index(i) return self.podcasts_menu.select_by_index(0) self.podcasts_menu.set_parent_screen(self) def add_screen_observers(self, update_observer, redraw_observer): """ Add screen observers :param update_observer: observer for updating the screen :param redraw_observer: observer to redraw the whole screen """ MenuScreen.add_screen_observers(self, update_observer, redraw_observer) self.update_observer = update_observer self.redraw_observer = redraw_observer self.add_loading_listener(redraw_observer) for b in self.navigator.menu_buttons: self.add_button_observers(b, update_observer, redraw_observer)
class RadioGroupScreen(MenuScreen): """ Radio group screen """ def __init__(self, util, listeners, voice_assistant): self.util = util self.config = util.config self.groups_list = self.util.get_stations_folders() self.factory = Factory(util) d = [MENU_ROWS, MENU_COLUMNS] MenuScreen.__init__(self, util, listeners, MENU_ROWS, MENU_COLUMNS, voice_assistant, d, self.turn_page, page_in_title=False) self.total_pages = math.ceil(len(self.groups_list) / PAGE_SIZE) self.title = util.get_stations_top_folder() m = self.factory.create_genre_menu_button self.groups_menu = MultiPageMenu(util, self.next_page, self.previous_page, self.set_title, self.reset_title, self.go_to_page, m, MENU_ROWS, MENU_COLUMNS, None, (0, 0, 0), self.menu_layout, align=ALIGN_CENTER) self.groups_menu.add_listener(listeners[KEY_GENRE]) self.set_menu(self.groups_menu) color_dark_light = self.config[COLORS][COLOR_DARK_LIGHT] self.navigator = RadioGroupNavigator(self.util, self.layout.BOTTOM, listeners, color_dark_light, self.total_pages) self.components.append(self.navigator) current_name = self.get_current_group_name() if current_name == None: self.current_page = 1 else: try: current_group_index = self.groups_list.index(current_name) self.current_page = int(current_group_index / PAGE_SIZE) + 1 except: current_group_index = 0 self.turn_page() def get_current_group_name(self): key = STATIONS + "." + self.config[CURRENT][LANGUAGE] name = None try: name = self.config[key][CURRENT_STATIONS] except: pass return name def get_page(self): start = (self.current_page - 1) * PAGE_SIZE end = self.current_page * PAGE_SIZE page = self.groups_list[start:end] tmp_layout = self.groups_menu.get_layout(self.groups_list) button_rect = tmp_layout.constraints[0] groups_dict = self.util.load_stations_folders(button_rect) return self.util.get_radio_group_slice(groups_dict, start, end) def turn_page(self): """ Turn book genre page """ group_page = self.get_page() self.groups_menu.set_items(group_page, 0, self.change_group, False) current_name = self.get_current_group_name() try: self.current_genre = group_page[current_name] self.groups_menu.item_selected(self.current_genre) except: keys = list(group_page.keys()) self.groups_menu.item_selected(group_page[keys[0]]) if self.navigator and self.total_pages > 1: self.navigator.left_button.change_label(str(self.current_page - 1)) self.navigator.right_button.change_label( str(self.total_pages - self.current_page)) self.set_title(self.current_page) self.groups_menu.clean_draw_update() def change_group(self, state): """ Change group event listener :param state: button state """ if not self.visible: return self.current_genre = state key = STATIONS + "." + self.config[CURRENT][LANGUAGE] self.config[key][CURRENT_STATIONS] = state.genre state.source = GENRE self.groups_menu.notify_listeners(state) def add_screen_observers(self, update_observer, redraw_observer): """ Add screen observers :param update_observer: observer for updating the screen :param redraw_observer: observer to redraw the whole screen """ self.navigator.add_observers(update_observer, redraw_observer) self.groups_menu.add_menu_observers(update_observer, redraw_observer, release=False)
class WiFiScreen(MenuScreen): """ Wi-Fi Screen """ def __init__(self, util, listeners, voice_assistant): """ Initializer :param util: utility object :param listeners: listeners :param voice_assistant: voice assistant """ self.util = util self.config = util.config self.listeners = listeners self.factory = Factory(util) self.go_home = listeners[KEY_HOME] self.go_keyboard = listeners[KEY_KEYBOARD_KEY] self.keyboard_callback = listeners[KEY_CALLBACK] self.wifi_selection_listeners = [] self.wifi_util = WiFiUtil(util) self.bounding_box = util.screen_rect layout = BorderLayout(self.bounding_box) layout.set_percent_constraints(PERCENT_TOP_HEIGHT, PERCENT_BOTTOM_HEIGHT, 0, 0) d = [MENU_ROWS_WIFI, MENU_COLUMNS_WIFI] MenuScreen.__init__(self, util, listeners, MENU_ROWS_WIFI, MENU_COLUMNS_WIFI, voice_assistant, d, self.turn_page, page_in_title=False, show_loading=False) self.title = self.config[LABELS]["select.wifi"] self.set_title(1) m = self.factory.create_wifi_menu_button self.wifi_menu = MultiPageMenu(util, self.next_page, self.previous_page, self.set_title, self.reset_title, self.go_to_page, m, MENU_ROWS_WIFI, MENU_COLUMNS_WIFI, None, (0, 0, 0), self.menu_layout, align=ALIGN_CENTER) self.set_menu(self.wifi_menu) listeners[KEY_REFRESH] = self.set_current listeners[KEY_SORT] = self.sort_abc self.navigator = WiFiNavigator(self.util, self.layout.BOTTOM, listeners, PAGE_SIZE_WIFI + 1) self.components.append(self.navigator) self.original_networks = None self.networks = None self.sort_direction = False self.current_network = None def set_current(self, state): """ Set current state :param state: button state """ self.set_loading(self.title) info = self.wifi_util.get_wifi_networks() self.original_networks = info["networks"] if not self.original_networks: self.reset_loading() return self.networks = self.sort_networks(SORT_ALPHABETICALLY) self.current_network = info["profile"] self.total_pages = math.ceil(len(self.networks) / PAGE_SIZE_WIFI) self.reset_loading() self.current_page = self.wifi_util.get_page_num( self.current_network, self.networks) self.turn_page() def sort_networks(self, order): """ Sort networks :param order: sort order :return: sorted networks """ sorted_networks = [] if order == SORT_ALPHABETICALLY: sorted_networks = sorted(self.original_networks, key=lambda i: i["name"], reverse=self.sort_direction) else: sorted_networks = sorted(self.original_networks, key=lambda i: i["strength"], reverse=self.sort_direction) states = {} h = self.layout.CENTER.h / MENU_ROWS_WIFI bb = pygame.Rect(0, 0, h, h) for i, n in enumerate(sorted_networks): s = self.wifi_util.get_network_info(i, n["name"], n["strength"], bb) states[s.name] = s return states def sort_abc(self, state): """ Sort in alphabetical order :param state: button state """ self.sort(SORT_ALPHABETICALLY) def select_network(self, state=None): """ Select network from menu :param state: button state """ self.current_network = state.name self.notify_wifi_selection_listeners(self.current_network) state.title = self.config[LABELS]["enter.password"] state.callback = self.keyboard_callback self.go_keyboard(state) def sort(self, order): """ Sort by order :param order: sort order :return: """ self.sort_direction = not self.sort_direction self.current_page = 1 self.networks = self.sort_networks(order) self.turn_page() def turn_page(self): """ Turn page """ p = self.wifi_util.get_network_page(self.current_page, self.networks) self.wifi_menu.set_items(p, 0, self.select_network, False) keys = list(p.keys()) if len(keys) != 0 and self.navigator and self.total_pages > 1: self.navigator.left_button.change_label(str(self.current_page - 1)) self.navigator.right_button.change_label( str(self.total_pages - self.current_page)) self.set_title(self.current_page) self.wifi_menu.clean_draw_update() if hasattr(self, "update_observer"): self.wifi_menu.add_menu_observers(self.update_observer, self.redraw_observer) self.wifi_menu.unselect() for i, b in enumerate(self.wifi_menu.buttons.values()): if self.current_network == b.state.name: self.wifi_menu.select_by_index(b.state.index) return index = (self.current_page - 1) * PAGE_SIZE_WIFI self.wifi_menu.select_by_index(index) def add_wifi_selection_listener(self, listener): """ Add listener :param listener: event listener """ if listener not in self.wifi_selection_listeners: self.wifi_selection_listeners.append(listener) def notify_wifi_selection_listeners(self, selected_wifi): """ Notify all listeners :param selected_wifi: """ for listener in self.wifi_selection_listeners: listener(selected_wifi) def add_screen_observers(self, update_observer, redraw_observer): """ Add screen observers :param update_observer: observer for updating the screen :param redraw_observer: observer to redraw the whole screen """ MenuScreen.add_screen_observers(self, update_observer, redraw_observer) self.update_observer = update_observer self.redraw_observer = redraw_observer self.add_loading_listener(redraw_observer) for b in self.navigator.menu_buttons: self.add_button_observers(b, update_observer, redraw_observer)
class TopicScreen(MenuScreen): """ Collection Topic Screen """ def __init__(self, util, listeners, voice_assistant): """ Initializer :param util: utility object :param listeners: listeners :param voice_assistant: voice assistant """ self.util = util self.config = util.config self.listeners = listeners self.listeners[KEY_LIST] = self.set_list self.factory = Factory(util) dbutil = util.get_db_util() self.selector = Selector(dbutil) self.bounding_box = util.screen_rect layout = BorderLayout(self.bounding_box) layout.set_percent_constraints(PERCENT_TOP_HEIGHT, PERCENT_BOTTOM_HEIGHT, 0, 0) MenuScreen.__init__(self, util, listeners, ROWS, COLUMNS, voice_assistant, [ROWS, COLUMNS], self.turn_page, page_in_title=False, show_loading=False) m = self.factory.create_collection_menu_button self.topic_menu = MultiPageMenu(util, self.next_page, self.previous_page, self.set_title, self.reset_title, self.go_to_page, m, ROWS, COLUMNS, None, (0, 0, 0), self.menu_layout, align=ALIGN_LEFT) self.set_menu(self.topic_menu) self.navigator = TopicNavigator(self.util, self.layout.BOTTOM, listeners) self.components.append(self.navigator) self.current_topic = None self.current_item = None self.current_page_items = None self.first_item = None self.last_item = None self.collection_topic = None self.previous_page = 1 self.search_string = None self.source = None self.mode = KEY_LIST self.animated_title = True def set_current(self, state): """ Set current state :param state: button state """ self.source = getattr(state, KEY_SOURCE, None) if self.source: if self.source == KEY_ABC: self.mode = KEY_ABC elif self.source == KEY_SEARCH: self.mode = KEY_SEARCH elif self.source == KEY_LIST: self.mode = KEY_LIST self.topic_menu.select_by_index(self.topic_menu.selected_index) if self.current_topic and (self.source == KEY_NAVIGATOR or self.source == KEY_BACK or self.source == None): return if self.source == KEY_MENU: self.config[COLLECTION_PLAYBACK][COLLECTION_TOPIC] = state.name self.mode = KEY_LIST if hasattr(state, "genre"): if self.current_topic == state.genre: return else: self.current_topic = state.genre name = self.config[COLLECTION_PLAYBACK][COLLECTION_TOPIC] if self.source: if self.source == KEY_ABC: name = getattr(state, KEY_NAME, None) elif self.source == KEY_SEARCH: name = getattr(state, KEY_CALLBACK_VAR, None) if not self.source or not name: return if self.source != KEY_ABC and self.source != KEY_SEARCH: self.collection_topic = name self.search_string == None else: self.search_string = name self.navigator.set_buttons(self.collection_topic) self.navigator.left_button.change_label("0") self.navigator.right_button.change_label("0") self.current_page_items = None self.first_item = "" self.last_item = "" self.current_page = 1 self.previous_page = 1 if not self.current_topic: return self.title = self.get_title(name) self.set_title(1) self.set_loading(self.title) self.total_pages = self.get_total_pages(name) self.turn_page() self.reset_loading() def set_list(self, state=None): """ Set list view """ s = State() s.source = KEY_LIST s.name = self.collection_topic self.set_current(s) def get_title(self, search_string): """ Return title based on call source. The source can be: - Collection screen - ABC keyboard - Keyboard Search screen :param search_string: search string from keyboard :return: title which depends on call source """ title = None try: title = self.config[LABELS][self.collection_topic] except: pass if self.source == KEY_ABC: title = f"{title}. {search_string.strip()}" elif self.source == KEY_SEARCH: title = f"{title}. *{search_string.strip()}*" return title def get_total_pages(self, search_string): """ Return the number of total pages for defined search criteria :param search_string: search string from keyboard :return: total pages number """ mode = self.collection_topic if mode == KEY_AUDIO_FOLDER: mode = FOLDER elif mode == KEY_FILE: mode = FILENAME total_pages = 0 if self.source == KEY_ABC: total_pages = self.selector.get_page_count_by_char( mode, search_string.strip(), PAGE_SIZE) elif self.source == KEY_SEARCH: total_pages = self.selector.get_page_count_by_pattern( mode, search_string.strip(), PAGE_SIZE) else: total_pages = self.selector.get_page_count(mode, PAGE_SIZE) return total_pages def turn_page(self): """ Turn page """ if self.total_pages == 0: self.topic_menu.set_items({}, 0, self.select_item, False) return p = self.prepare_page() self.topic_menu.set_items(p, 0, self.select_item, False) keys = list(p.keys()) if len(keys) != 0 and self.navigator and self.total_pages > 1: self.navigator.left_button.change_label(str(self.current_page - 1)) self.navigator.right_button.change_label( str(self.total_pages - self.current_page)) self.topic_menu.clean_draw_update() if hasattr(self, "update_observer"): self.topic_menu.add_menu_observers(self.update_observer, self.redraw_observer) self.topic_menu.unselect() for b in self.topic_menu.buttons.values(): if self.current_item == b.state.name: self.topic_menu.select_by_index(b.state.index) return index = (self.current_page - 1) * PAGE_SIZE self.topic_menu.select_by_index(index) def prepare_page(self): """ Prepare topic page :return: page dictionary """ page, self.first_item, self.last_item, self.current_item = self.get_current_page( ) p = {} for i, n in enumerate(page): s = State() s.index = i if "\x00" in n: n = n.replace("\x00", "") s.name = n s.l_name = n p[str(i)] = s return p def get_current_page(self): """ Get current page content :return: page content """ topic = self.collection_topic if topic == KEY_AUDIO_FOLDER: topic = FOLDER elif topic == KEY_FILE: topic = FILENAME page_items = self.selector.get_topic_page( self.mode, topic, self.search_string, self.current_page, self.previous_page, self.first_item, self.last_item, PAGE_SIZE) self.previous_page = self.current_page if not page_items: page_items = [] current_item = None first_item = None last_item = None else: current_item = page_items[0] first_item = current_item last_item = page_items[len(page_items) - 1] return (page_items, first_item, last_item, current_item) def select_item(self, s=None): """ Select item from menu :param s: button state """ if not s: return s.collection_topic = self.collection_topic self.topic_menu.selected_index = s.index if self.collection_topic == KEY_AUDIO_FOLDER: s.folder = os.path.join(self.config[COLLECTION][BASE_FOLDER], s.name[1:]) s.source = KEY_MENU files = self.util.get_audio_files_in_folder(s.folder, False) if files: f = files[0] s.file_name = f.file_name s.url = os.path.join(s.folder, s.file_name) else: s.file_name = None s.url = None self.listeners[TOPIC_DETAIL](s) def add_screen_observers(self, update_observer, redraw_observer): """ Add screen observers :param update_observer: observer for updating the screen :param redraw_observer: observer to redraw the whole screen """ MenuScreen.add_screen_observers(self, update_observer, redraw_observer) self.update_observer = update_observer self.redraw_observer = redraw_observer self.add_loading_listener(redraw_observer) self.topic_menu.add_menu_observers(update_observer, redraw_observer) self.navigator.add_observers(update_observer, redraw_observer)
class PodcastsScreen(MenuScreen): """ Podcasts Screen """ def __init__(self, util, listeners, voice_assistant): """ Initializer :param util: utility object :param listeners: listeners :param voice_assistant: voice assistant """ self.util = util self.config = util.config self.listeners = listeners self.factory = Factory(util) self.podcasts_util = util.get_podcasts_util() self.bounding_box = util.screen_rect layout = BorderLayout(self.bounding_box) layout.set_percent_constraints(PERCENT_TOP_HEIGHT, PERCENT_BOTTOM_HEIGHT, 0, 0) d = [MENU_ROWS_PODCASTS, MENU_COLUMNS_PODCASTS] MenuScreen.__init__(self, util, listeners, MENU_ROWS_PODCASTS, MENU_COLUMNS_PODCASTS, voice_assistant, d, self.turn_page, page_in_title=False, show_loading=True) self.title = self.config[LABELS][PODCASTS] m = self.factory.create_podcast_menu_button self.podcasts_menu = MultiPageMenu(util, self.next_page, self.previous_page, self.set_title, self.reset_title, self.go_to_page, m, MENU_ROWS_PODCASTS, MENU_COLUMNS_PODCASTS, None, (0, 0, 0), self.menu_layout, align=ALIGN_CENTER) self.set_menu(self.podcasts_menu) self.navigator = PodcastNavigator( self.util, self.layout.BOTTOM, listeners, self.config[COLORS][COLOR_DARK_LIGHT], PAGE_SIZE_PODCASTS + 1) self.components.append(self.navigator) url = self.config[PODCASTS][PODCAST_URL] if url and len(url) > 0: self.current_page = self.podcasts_util.get_podcast_page( url, PAGE_SIZE_PODCASTS) else: self.current_page = 1 self.animated_title = True def set_current(self, state): """ Set current state :param state: button state """ if self.util.connected_to_internet: podcast_links_num = len(self.podcasts_util.get_podcasts_links()) else: podcast_links_num = len(self.podcasts_util.load_podcasts()) self.total_pages = math.ceil(podcast_links_num / PAGE_SIZE_PODCASTS) self.set_loading(self.title) self.turn_page() self.reset_loading() def turn_page(self): """ Turn podcasts page """ page = {} if self.util.connected_to_internet: page = self.podcasts_util.get_podcasts(self.current_page, PAGE_SIZE_PODCASTS) if len(list(page.keys())) == 0 or not self.util.connected_to_internet: page = self.podcasts_util.get_podcasts_from_disk( self.current_page, PAGE_SIZE_PODCASTS) self.podcasts_menu.set_items(page, 0, self.listeners[KEY_PODCAST_EPISODES], False) keys = list(page.keys()) if len(keys) != 0: self.podcasts_menu.item_selected(page[keys[0]]) if self.navigator and self.total_pages > 1: self.navigator.left_button.change_label( str(self.current_page - 1)) self.navigator.right_button.change_label( str(self.total_pages - self.current_page)) self.set_title(self.current_page) self.podcasts_menu.clean_draw_update() if hasattr(self, "update_observer"): self.podcasts_menu.add_menu_observers(self.update_observer, self.redraw_observer) self.podcasts_menu.unselect() for i, b in enumerate(self.podcasts_menu.buttons.values()): url = self.config[PODCASTS][PODCAST_URL] if url == b.state.url: self.podcasts_menu.select_by_index(i) return self.podcasts_menu.select_by_index(0) def add_screen_observers(self, update_observer, redraw_observer): """ Add screen observers :param update_observer: observer for updating the screen :param redraw_observer: observer to redraw the whole screen """ MenuScreen.add_screen_observers(self, update_observer, redraw_observer) self.update_observer = update_observer self.redraw_observer = redraw_observer self.add_loading_listener(redraw_observer) for b in self.navigator.menu_buttons: self.add_button_observers(b, update_observer, redraw_observer)
class PodcastEpisodesScreen(MenuScreen): """ Podcast Episodes Screen """ def __init__(self, util, listeners, voice_assistant, state): """ Initializer :param util: utility object :param listeners: file browser listeners :param voice_assistant: voice assistant :param state: button state """ self.util = util self.config = util.config self.podcasts_util = util.get_podcasts_util() self.listeners = listeners self.factory = Factory(util) self.bounding_box = util.screen_rect self.layout = BorderLayout(self.bounding_box) self.layout.set_percent_constraints(PERCENT_TOP_HEIGHT, PERCENT_BOTTOM_HEIGHT, 0, 0) d = [MENU_ROWS_EPISODES, MENU_COLUMNS_EPISODES] MenuScreen.__init__(self, util, listeners, MENU_ROWS_EPISODES, MENU_COLUMNS_EPISODES, voice_assistant, d, self.turn_page, page_in_title=False) if hasattr(state, "podcast_url"): podcast_url = state.podcast_url self.title = self.podcasts_util.summary_cache[podcast_url].name else: self.title = state.name self.total_pages = PAGE_SIZE_EPISODES * 2 self.episodes = [] self.navigator = EpisodeNavigator(self.util, self.layout.BOTTOM, listeners, self.total_pages) self.add_navigator(self.navigator) self.current_page = 1 self.current_item = None m = self.create_episode_menu_button font_size = int(((self.menu_layout.h / MENU_ROWS_EPISODES) / 100) * FONT_HEIGHT) self.episodes_menu = MultiPageMenu(util, self.next_page, self.previous_page, self.set_title, self.reset_title, self.go_to_page, m, MENU_ROWS_EPISODES, MENU_COLUMNS_EPISODES, None, (0, 0, 0, 0), self.menu_layout, align=ALIGN_CENTER, font_size=font_size) self.set_menu(self.episodes_menu) self.save_episode_listeners = [] self.animated_title = True def create_episode_menu_button(self, s, constr, action, scale, font_size): """ Create podcast episode menu button :param s: button state :param constr: scaling constraints :param action: button event listener :param scale: True - scale images, False - don't scale images :param font_size: label font height in pixels :return: genre menu button """ s.bounding_box = constr s.img_x = None s.img_y = None s.auto_update = True s.show_bgr = True s.show_img = True s.show_label = True s.image_location = LEFT s.label_location = CENTER s.label_area_percent = 30 s.image_size_percent = 0.12 s.text_color_normal = self.config[COLORS][COLOR_BRIGHT] s.text_color_selected = self.config[COLORS][COLOR_CONTRAST] s.text_color_disabled = self.config[COLORS][COLOR_MEDIUM] s.text_color_current = s.text_color_normal s.scale = scale s.source = "episode_menu" s.v_align = V_ALIGN_TOP s.h_align = H_ALIGN_LEFT s.v_offset = (constr.h/100) * 5 s.bgr = self.config[BACKGROUND][MENU_BGR_COLOR] s.image_area_percent = ICON_AREA s.fixed_height = font_size button = EpisodeButton(self.util, s) button.add_release_listener(action) if not getattr(s, "enabled", True): button.set_enabled(False) elif getattr(s, "icon_base", False) and not getattr(s, "scaled", False): button.components[1].content = s.icon_base button.scaled = scale return button def set_current(self, state): """ Set current state :param state: button state """ if not self.util.connected_to_internet and len(self.episodes) == 0 and not hasattr(state, "url"): return if state.name == KEY_BACK or (getattr(state, "source", None) == FILE_BUTTON and len(self.episodes) != 0): self.episodes_menu.clean_draw_update() return if getattr(state, "podcast_url", None) != None: self.episodes = self.podcasts_util.get_episodes(state.podcast_url) if len(self.episodes) != 0: self.total_pages = math.ceil(len(self.episodes) / PAGE_SIZE_EPISODES) self.turn_page(state) return self.set_loading(self.title) if state.name != self.title or len(self.episodes) == 0: self.title = state.name if self.util.connected_to_internet: self.episodes = self.podcasts_util.get_episodes(state.url) else: self.episodes = self.podcasts_util.get_episodes_from_disk(state.url) self.total_pages = math.ceil(len(self.episodes) / PAGE_SIZE_EPISODES) self.turn_page(state) self.reset_loading() def turn_page(self, state=None): """ Turn screen page :param state: button state """ filelist = Page(self.episodes, MENU_ROWS_EPISODES, MENU_COLUMNS_EPISODES) if state == None: pass filelist.current_page_index = self.current_page - 1 index = -1 else: if getattr(state, "status", None) == STATUS_LOADED: if hasattr(state, "original_url") and len(state.original_url.strip()) > 0: filelist.set_current_item_by_url(state.original_url) else: filelist.set_current_item_by_file_name(state.file_name) else: filelist.set_current_item_by_url(state.url) index = filelist.current_item_index self.current_item = self.config[PODCASTS][PODCAST_EPISODE_NAME] self.current_page = filelist.current_page_index + 1 page = filelist.get_current_page() d = self.episodes_menu.make_dict(page) self.episodes_menu.set_items(d, filelist.current_page_index, self.select_episode, False) self.set_title(self.current_page) self.episodes_menu.unselect() self.episodes_menu.select_by_index(index) for b in self.episodes_menu.buttons.values(): b.parent_screen = self self.navigator.get_button_by_name(KEY_PAGE_DOWN).change_label(str(filelist.get_left_items_number())) self.navigator.get_button_by_name(KEY_PAGE_UP).change_label(str(filelist.get_right_items_number())) self.episodes_menu.clean_draw_update() if hasattr(self, "update_observer"): self.episodes_menu.add_menu_observers(self.update_observer, self.redraw_observer) self.link_borders() menu_selected = self.menu.get_selected_index() if menu_selected == None: if self.current_item == None or len(self.current_item) == 0: self.menu.select_by_index(0) item = self.menu.get_selected_item() if item != None: self.current_item = item.state.name for b in self.menu.buttons.values(): b.parent_screen = self if self.current_item == b.state.name: self.menu.select_by_index(b.state.index) self.navigator.unselect() return def select_episode(self, state): """ Select podacst episode :param state: button state """ if getattr(state, "long_press", None) == True: if state.status == STATUS_LOADED: self.podcasts_util.delete_episode(state) if not self.util.connected_to_internet: for i, c in enumerate(self.episodes): if c.name == state.name: del self.episodes[i] break if len(self.episodes) == 0: self.title = " " self.set_title(0) self.turn_page(state) else: state.icon_base = state.event_origin.components[1].content = self.podcasts_util.available_icon state.status = STATUS_AVAILABLE elif state.status == STATUS_AVAILABLE: if self.podcasts_util.is_podcast_folder_available(): state.icon_base = state.event_origin.components[1].content = self.podcasts_util.loading_icon state.status = STATUS_LOADING self.add_save_episode_listener(state) self.podcasts_util.save_episode(state, self.notify_save_episode_listeners) self.clean_draw_update() else: self.current_item = state.name podcast_player = self.listeners[KEY_PLAYER] podcast_player(state) def add_save_episode_listener(self, listener): """ Add save episode listener :param listener: event listener """ if listener not in self.save_episode_listeners: self.save_episode_listeners.append(listener) def notify_save_episode_listeners(self): """ Notify all save episode listeners """ for index, listener in enumerate(self.save_episode_listeners): listener.icon_base = listener.event_origin.components[1].content = self.podcasts_util.loaded_icon listener.status = STATUS_LOADED self.clean_draw_update() if hasattr(self, "redraw_observer"): self.redraw_observer() del self.save_episode_listeners[index] def handle_event(self, event): """ Handle screen event :param event: the event to handle """ self.handle_event_common(event) def add_screen_observers(self, update_observer, redraw_observer): """ Add screen observers :param update_observer: observer for updating the screen :param redraw_observer: observer to redraw the whole screen """ MenuScreen.add_screen_observers(self, update_observer, redraw_observer) self.update_observer = update_observer self.redraw_observer = redraw_observer self.add_loading_listener(redraw_observer) self.navigator.add_observers(self.update_observer, self.redraw_observer)
class BookAuthor(MenuScreen): """ Authors screen """ def __init__(self, util, listeners, ch, f, go_author, parser, base_url, voice_assistant, d): """ Initializer :param util: utility object :param listeners: screen listeners :param ch: selected character :param f: selected filter :param go_authors: callback :param parser: authors parser :param base_url: url :param d: dictionary with menu button flags """ self.util = util self.factory = Factory(util) self.base_url = base_url self.config = util.config self.parser = parser self.current_author_char = ch self.current_author_filter = f self.go_author = go_author self.author_cache = {} self.title = self.config[LABELS][KEY_AUTHORS] MenuScreen.__init__(self, util, listeners, MENU_ROWS, MENU_COLUMNS, voice_assistant, d, self.turn_page) m = self.create_book_author_menu_button font_size = int(((self.menu_layout.h / MENU_ROWS) / 100) * self.config[FONT_HEIGHT_PERCENT]) self.authors_menu = MultiPageMenu(util, self.next_page, self.previous_page, self.set_title, self.reset_title, self.go_to_page, m, MENU_ROWS, MENU_COLUMNS, None, (0, 0, 0), self.menu_layout, font_size=font_size) self.set_menu(self.authors_menu) self.navigator = BookNavigator(util, self.layout.BOTTOM, listeners, d[4]) self.add_component(self.navigator) def create_book_author_menu_button(self, s, constr, action, scale, font_size): """ Create Author Menu button :param s: button state :param constr: bounding box :param action: button event listener :param show_img: True - show image, False - don't show image :param show_label: True - show label, False - don't show label :return: genre menu button """ s.bounding_box = constr s.img_x = None s.img_y = None s.auto_update = True s.show_bgr = True s.show_img = False s.show_label = True s.text_color_normal = self.config[COLORS][COLOR_BRIGHT] s.text_color_selected = self.config[COLORS][COLOR_CONTRAST] s.text_color_disabled = self.config[COLORS][COLOR_MEDIUM] s.text_color_current = s.text_color_normal s.fixed_height = font_size button = Button(self.util, s) button.add_release_listener(action) return button def create_book_author_items(self, authors): """ Create dictionary with author books :param authors: list of author books :return: dictionary with author books """ items = {} for i, g in enumerate(authors): state = State() state.name = g[AUTHOR_NAME] state.url = g[AUTHOR_URL] + "/" try: state.l_name = state.name + " (" + g[AUTHOR_BOOKS] + ")" except: state.l_name = state.name state.bgr = self.config[COLORS][COLOR_DARK] state.img_x = None state.img_y = None state.auto_update = True state.show_bgr = True state.show_img = False state.show_label = True state.comparator_item = state.name state.index = i items[state.name] = state return items def set_current(self, ch=None, f=None): """ Apply selected character and filter :param ch: selected character :param f: selected filter """ if not ch and not f: return self.set_loading(self.config[LABELS][KEY_AUTHORS]) self.total_pages = 0 self.current_page = 1 self.current_author_char = ch self.current_author_filter = f try: self.author_cache[ch] except: self.get_authors() self.turn_page() self.reset_loading() def get_authors(self): """ Get authors from parser """ self.parser.author_parser.current_author_char = self.current_author_char self.parser.author_parser.url = self.base_url authors = self.parser.get_authors() if authors: self.author_cache[self.current_author_char] = authors def turn_page(self): """ Turn authors page """ self.authors_menu.set_items({}, 0, self.go_author) filtered_authors = [] for a in self.author_cache[self.current_author_char]: if self.current_author_filter: if a[AUTHOR_NAME].startswith(self.current_author_filter): filtered_authors.append(a) else: filtered_authors.append(a) start = (self.current_page - 1) * PAGE_SIZE end = self.current_page * PAGE_SIZE page = filtered_authors[start:end] self.author_dict = self.create_book_author_items(page) self.authors_menu.set_items(self.author_dict, 0, self.go_author, False) self.authors_menu.align_content(ALIGN_LEFT) self.authors_menu.select_by_index(0) self.authors_menu.clean_draw_update() self.total_pages = math.ceil(len(filtered_authors) / PAGE_SIZE) left = str(self.current_page - 1) if self.total_pages == 0: right = "0" else: right = str(self.total_pages - self.current_page) self.navigator.left_button.change_label(left) self.navigator.right_button.change_label(right) self.set_title(self.current_page) def add_screen_observers(self, update_observer, redraw_observer): """ Add screen observers :param update_observer: observer for updating the screen :param redraw_observer: observer to redraw the whole screen """ self.navigator.add_observers(update_observer, redraw_observer) self.authors_menu.add_menu_loaded_listener(redraw_observer) self.authors_menu.add_menu_observers(update_observer, redraw_observer, release=False)
class BookAuthor(MenuScreen): """ Authors screen """ def __init__(self, util, listeners, ch, f, go_author, parser, base_url, voice_assistant, d): """ Initializer :param util: utility object :param listeners: screen listeners :param ch: selected character :param f: selected filter :param go_authors: callback :param parser: authors parser :param base_url: url :param d: dictionary with menu button flags """ self.util = util self.factory = Factory(util) self.base_url = base_url self.config = util.config self.parser = parser self.current_author_char = ch self.current_author_filter = f self.go_author = go_author self.author_cache = {} self.title = self.config[LABELS][KEY_AUTHORS] MenuScreen.__init__(self, util, listeners, MENU_ROWS, MENU_COLUMNS, voice_assistant, d, self.turn_page) m = self.factory.create_book_author_menu_button self.authors_menu = MultiPageMenu(util, self.next_page, self.previous_page, self.set_title, self.reset_title, self.go_to_page, m, MENU_ROWS, MENU_COLUMNS, None, (0, 0, 0), self.menu_layout) self.set_menu(self.authors_menu) def set_current(self, ch=None, f=None): """ Apply selected character and filter :param ch: selected character :param f: selected filter """ if not ch and not f: return self.set_loading(self.config[LABELS][KEY_AUTHORS]) self.total_pages = 0 self.current_page = 1 self.current_author_char = ch self.current_author_filter = f try: self.author_cache[ch] except: self.get_authors() self.turn_page() self.reset_loading() def get_authors(self): """ Get authors from parser """ self.parser.author_parser.current_author_char = self.current_author_char self.parser.author_parser.url = self.base_url authors = self.parser.get_authors() if authors: self.author_cache[self.current_author_char] = authors def turn_page(self): """ Turn authors page """ self.authors_menu.set_items({}, 0, self.go_author) filtered_authors = [] for a in self.author_cache[self.current_author_char]: if self.current_author_filter: if a[AUTHOR_NAME].startswith(self.current_author_filter): filtered_authors.append(a) else: filtered_authors.append(a) start = (self.current_page - 1) * PAGE_SIZE end = self.current_page * PAGE_SIZE page = filtered_authors[start:end] self.author_dict = self.factory.create_book_author_items(page) self.authors_menu.set_items(self.author_dict, 0, self.go_author, False) self.authors_menu.align_content(ALIGN_LEFT) self.authors_menu.select_by_index(0) self.authors_menu.clean_draw_update() self.total_pages = math.ceil(len(filtered_authors) / PAGE_SIZE) left = str(self.current_page - 1) if self.total_pages == 0: right = "0" else: right = str(self.total_pages - self.current_page) self.navigator.left_button.change_label(left) self.navigator.right_button.change_label(right) self.set_title(self.current_page) def add_screen_observers(self, update_observer, redraw_observer): """ Add screen observers :param update_observer: observer for updating the screen :param redraw_observer: observer to redraw the whole screen """ self.navigator.add_observers(update_observer, redraw_observer) self.authors_menu.add_menu_loaded_listener(redraw_observer) self.authors_menu.add_menu_observers(update_observer, redraw_observer, release=False)
class RadioGroupScreen(MenuScreen): """ Radio group screen """ def __init__(self, util, listeners, voice_assistant): self.util = util self.config = util.config self.groups_list = self.util.get_stations_folders() self.factory = Factory(util) d = [MENU_ROWS, MENU_COLUMNS] MenuScreen.__init__(self, util, listeners, MENU_ROWS, MENU_COLUMNS, voice_assistant, d, self.turn_page, page_in_title=False) self.total_pages = math.ceil(len(self.groups_list) / PAGE_SIZE) self.title = util.get_stations_top_folder() m = self.create_genre_menu_button label_area = ( (self.menu_layout.h / MENU_ROWS) / 100) * (100 - ICON_AREA) font_size = int((label_area / 100) * FONT_HEIGHT) self.groups_menu = MultiPageMenu(util, self.next_page, self.previous_page, self.set_title, self.reset_title, self.go_to_page, m, MENU_ROWS, MENU_COLUMNS, None, (0, 0, 0, 0), self.menu_layout, align=ALIGN_CENTER, font_size=font_size) self.groups_menu.add_listener(listeners[KEY_GENRE]) self.set_menu(self.groups_menu) color_dark_light = self.config[COLORS][COLOR_DARK_LIGHT] self.navigator = RadioGroupNavigator(self.util, self.layout.BOTTOM, listeners, color_dark_light, self.total_pages) self.add_component(self.navigator) current_name = self.get_current_group_name() if current_name == None: self.current_page = 1 else: try: current_group_index = self.groups_list.index(current_name) self.current_page = int(current_group_index / PAGE_SIZE) + 1 except: current_group_index = 0 self.turn_page() def create_genre_menu_button(self, s, constr, action, scale, font_size): """ Create Genre Menu button :param s: button state :param constr: scaling constraints :param action: button event listener :param scale: True - scale images, False - don't scale images :return: genre menu button """ s.padding = BUTTON_PADDING s.image_area_percent = ICON_AREA s.fixed_height = font_size s.v_align = CENTER return self.factory.create_menu_button(s, constr, action, scale, font_size=font_size) def get_current_group_name(self): key = STATIONS + "." + self.config[CURRENT][LANGUAGE] name = None try: name = self.config[key][CURRENT_STATIONS] except: pass return name def get_page(self): start = (self.current_page - 1) * PAGE_SIZE end = self.current_page * PAGE_SIZE tmp_layout = self.groups_menu.get_layout(self.groups_list) button_rect = tmp_layout.constraints[0] image_box = self.factory.get_icon_bounding_box(button_rect, ICON_LOCATION, ICON_AREA, ICON_SIZE, BUTTON_PADDING) groups_dict = self.util.load_stations_folders(image_box) return self.util.get_radio_group_slice(groups_dict, start, end) def turn_page(self): """ Turn book genre page """ group_page = self.get_page() self.groups_menu.set_items(group_page, 0, self.change_group, False) current_name = self.get_current_group_name() try: self.current_genre = group_page[current_name] self.groups_menu.item_selected(self.current_genre) except: keys = list(group_page.keys()) self.groups_menu.item_selected(group_page[keys[0]]) if self.navigator and self.total_pages > 1: self.navigator.left_button.change_label(str(self.current_page - 1)) self.navigator.right_button.change_label( str(self.total_pages - self.current_page)) for b in self.groups_menu.buttons.values(): b.parent_screen = self self.set_title(self.current_page) self.groups_menu.clean_draw_update() def change_group(self, state): """ Change group event listener :param state: button state """ if not self.visible: return self.current_genre = state key = STATIONS + "." + self.config[CURRENT][LANGUAGE] self.config[key][CURRENT_STATIONS] = state.genre state.source = GENRE self.groups_menu.notify_listeners(state) def add_screen_observers(self, update_observer, redraw_observer): """ Add screen observers :param update_observer: observer for updating the screen :param redraw_observer: observer to redraw the whole screen """ self.navigator.add_observers(update_observer, redraw_observer) self.groups_menu.add_menu_observers(update_observer, redraw_observer, release=False)
class BookGenre(MenuScreen): """ Bokk genre screen """ def __init__(self, util, listeners, go_book_by_genre, genres, base_url, voice_assistant, d): self.util = util self.go_book_by_genre = go_book_by_genre self.config = util.config self.genres_list = genres self.base_url = base_url self.factory = Factory(util) MenuScreen.__init__(self, util, listeners, MENU_ROWS, MENU_COLUMNS, voice_assistant, d, self.turn_page) self.total_pages = math.ceil(len(genres) / PAGE_SIZE) self.title = self.config[LABELS][KEY_CHOOSE_GENRE] m = self.create_book_genre_menu_button font_size = int(((self.menu_layout.h / MENU_ROWS) / 100) * self.config[FONT_HEIGHT_PERCENT]) self.genre_menu = MultiPageMenu(util, self.next_page, self.previous_page, self.set_title, self.reset_title, self.go_to_page, m, MENU_ROWS, MENU_COLUMNS, None, (0, 0, 0, 0), self.menu_layout, font_size=font_size) self.set_menu(self.genre_menu) self.navigator = BookNavigator(util, self.layout.BOTTOM, listeners, d[4]) self.add_component(self.navigator) self.turn_page() def create_book_genre_menu_button(self, s, constr, action, show_img=True, show_label=True): """ Create Genre Menu button :param s: button state :param constr: bounding box :param action: button event listener :param show_img: True - show image, False - don't show image :param show_label: True - show label, False - don't show label :return: genre menu button """ s.bounding_box = constr s.img_x = None s.img_y = None s.auto_update = True s.show_bgr = True s.show_img = show_img s.show_label = show_label s.text_color_normal = self.config[COLORS][COLOR_BRIGHT] s.text_color_selected = self.config[COLORS][COLOR_CONTRAST] s.text_color_disabled = self.config[COLORS][COLOR_MEDIUM] s.text_color_current = s.text_color_normal s.label_text_height = 35 s.bgr = self.config[BACKGROUND][MENU_BGR_COLOR] button = Button(self.util, s) button.add_release_listener(action) return button def turn_page(self): """ Turn book genre page """ start = (self.current_page - 1) * PAGE_SIZE end = self.current_page * PAGE_SIZE page = self.genres_list[start:end] self.genres_dict = self.factory.create_book_genre_items( page, self.base_url) self.genre_menu.set_items(self.genres_dict, 0, self.go_book_by_genre, False) self.genre_menu.align_content(ALIGN_LEFT) for b in self.genre_menu.buttons.values(): b.parent_screen = self self.genre_menu.select_by_index(0) self.genre_menu.clean_draw_update() self.navigator.left_button.change_label(str(self.current_page - 1)) self.navigator.right_button.change_label( str(self.total_pages - self.current_page)) self.set_title(self.current_page) def add_screen_observers(self, update_observer, redraw_observer): """ Add screen observers :param update_observer: observer for updating the screen :param redraw_observer: observer to redraw the whole screen """ self.navigator.add_observers(update_observer, redraw_observer) self.genre_menu.add_menu_observers(update_observer, redraw_observer, release=False)