Ejemplo n.º 1
0
    def __init__(self, util, listeners, voice_assistant):
        """ Initializer
        
        :param util: utility object
        :param listener: screen menu event listener
        """
        self.util = util
        config = util.config
        screen_layout = BorderLayout(util.screen_rect)
        top = int((util.screen_rect.h * PERCENT_SAVERS) / 100)
        bottom = util.screen_rect.h - top
        screen_layout.set_pixel_constraints(top, bottom, 0, 0)

        layout = BorderLayout(screen_layout.TOP)
        layout.set_percent_constraints(PERCENT_TOP_HEIGHT, 0, 0, 0)

        Screen.__init__(self,
                        util,
                        "",
                        PERCENT_TOP_HEIGHT,
                        voice_assistant,
                        "saver_title",
                        title_layout=layout.TOP)
        factory = Factory(util)

        self.bounding_box = util.screen_rect
        self.saver_menu = SaverMenu(util, None, layout.CENTER)
        self.add_component(self.saver_menu)

        b = config[BACKGROUND][HEADER_BGR_COLOR]
        c = config[COLORS][COLOR_CONTRAST]

        font_size = (layout.TOP.h * PERCENT_TITLE_FONT) / 100.0
        label = config[LABELS][SCREENSAVER]
        self.screen_title.set_text(label)

        layout = BorderLayout(screen_layout.BOTTOM)
        layout.set_percent_constraints(PERCENT_DELAY_TITLE,
                                       PERCENT_DELAY_TITLE, 0, 0)
        self.delay_menu = SaverDelayMenu(util, None, layout.CENTER)
        self.add_component(self.delay_menu)

        layout.TOP.y += 2
        layout.TOP.h -= 2
        self.saver_delay_title = factory.create_output_text(
            "saver_delay_title", layout.TOP, b, c, int(font_size))
        label = config[LABELS][DELAY]
        self.saver_delay_title.set_text(label)
        self.add_component(self.saver_delay_title)

        b = self.config[BACKGROUND][FOOTER_BGR_COLOR]
        self.navigator = SaverNavigator(util, listeners, b, layout.BOTTOM)
        self.add_component(self.navigator)

        self.top_menu_enabled = True
Ejemplo n.º 2
0
    def __init__(self, util, listeners, voice_assistant):
        """ Initializer
        
        :param util: utility object
        :param listener: screen menu event listener
        """
        self.util = util
        config = util.config
        screen_layout = BorderLayout(config[SCREEN_RECT])
        top = int((config[SCREEN_RECT].h * PERCENT_SAVERS) / 100)
        bottom = config[SCREEN_RECT].h - top
        screen_layout.set_pixel_constraints(top, bottom, 0, 0)
        
        layout = BorderLayout(screen_layout.TOP)
        layout.set_percent_constraints(PERCENT_TOP_HEIGHT, 0, 0, 0)
        
        Screen.__init__(self, util, "", PERCENT_TOP_HEIGHT, voice_assistant, "saver_title", title_layout=layout.TOP)
        factory = Factory(util)
        
        self.bounding_box = config[SCREEN_RECT]
        self.bgr = (0, 0, 0)
                
        self.saver_menu = SaverMenu(util, (0, 0, 0), layout.CENTER)
        self.add_component(self.saver_menu)
        
        d = config[COLORS][COLOR_DARK_LIGHT]
        c = config[COLORS][COLOR_CONTRAST]
        
        font_size = (layout.TOP.h * PERCENT_TITLE_FONT)/100.0
        label = config[LABELS][SCREENSAVER]
        self.screen_title.set_text(label)
        
        layout = BorderLayout(screen_layout.BOTTOM)
        layout.set_percent_constraints(PERCENT_DELAY_TITLE, PERCENT_DELAY_TITLE, 0, 0)
        self.delay_menu = SaverDelayMenu(util, (0, 0, 0), layout.CENTER)
        self.add_component(self.delay_menu)
        
        layout.TOP.y += 1
        layout.TOP.h -= 1
        self.saver_delay_title = factory.create_output_text("saver_delay_title", layout.TOP, d, c, int(font_size))
        label = config[LABELS][DELAY]
        self.saver_delay_title.set_text(label)
        self.add_component(self.saver_delay_title)
        
        buttons = factory.create_home_player_buttons(self, layout.BOTTOM, listeners)
        self.home_button = buttons[0]
        self.player_button = buttons[1]

        self.top_menu_enabled = True
Ejemplo n.º 3
0
    def __init__(self, util):
        """ Initializer
        
        :param util: utility object
        """
        self.util = util
        self.config = util.config
        self.color_web_bgr = self.config[COLORS][COLOR_WEB_BGR]
        Container.__init__(self, util, background=self.color_web_bgr)
        self.bounding_box = util.screen_rect
        self.start_listeners = []
        factory = Factory(util)
        edition = "Holbein Edition"

        layout = BorderLayout(self.bounding_box)
        layout.set_percent_constraints(0, PERCENT_FOOTER_HEIGHT, 0, 0)
        release_font_size = (layout.BOTTOM.h * PERCENT_FOOTER_FONT) / 100.0

        color_logo = self.config[COLORS][COLOR_LOGO]
        button = factory.create_image_button("peppy",
                                             bounding_box=layout.CENTER,
                                             bgr=self.color_web_bgr,
                                             image_size_percent=68,
                                             selected=False)
        x = layout.CENTER.w / 2 - button.components[1].content.get_size()[0] / 2
        y = layout.CENTER.h / 2 - button.components[1].content.get_size()[1] / 2
        button.components[1].content_x = x
        button.components[1].content_y = y
        self.add_component(button)

        layout.BOTTOM.y -= 1
        layout.BOTTOM.h += 1
        release = factory.create_output_text("about-name",
                                             layout.BOTTOM,
                                             self.color_web_bgr,
                                             color_logo,
                                             int(release_font_size),
                                             full_width=True,
                                             valign=V_ALIGN_TOP)
        release.set_text_no_draw(edition)
        self.add_component(release)
Ejemplo n.º 4
0
    def __init__(self, util, title_key):
        """ Initializer
        
        :param util: utility object
        :param title_key: the resource bundle key for the screen title
        """
        Container.__init__(self, util)
        self.util = util
        factory = Factory(util)
        config = util.config
        self.bounding_box = config[SCREEN_RECT]
        self.bgr = (0, 0, 0)
        self.layout = BorderLayout(config[SCREEN_RECT])
        self.layout.set_percent_constraints(PERCENT_TOP_HEIGHT, 0, 0, 0)

        font_size = (self.layout.TOP.h * PERCENT_TITLE_FONT)/100.0
        d = config[COLORS][COLOR_DARK]
        c = config[COLORS][COLOR_CONTRAST]
        self.screen_title = factory.create_output_text("screen_title", self.layout.TOP, d, c, int(font_size))
        label = config[LABELS][title_key]
        self.screen_title.set_text(label) 
        self.add_component(self.screen_title)
Ejemplo n.º 5
0
class NetworkScreen(MenuScreen):
    """ Network 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.factory = Factory(util)
        self.check_internet_connectivity = listeners[KEY_CHECK_INTERNET]
        self.go_home = listeners[KEY_HOME]
        self.set_modes = listeners[KEY_SET_MODES]
        self.linux = self.config[LINUX_PLATFORM]

        self.wifi_util = WiFiUtil(util)
        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)

        rows = 7
        if self.linux and self.config[USAGE][USE_BLUETOOTH]:
            rows = 7
        else:
            rows = 6

        columns = 1
        d = [rows, columns]
        MenuScreen.__init__(self,
                            util,
                            listeners,
                            rows,
                            columns,
                            voice_assistant,
                            d,
                            None,
                            page_in_title=False,
                            show_loading=False)
        self.title = self.config[LABELS]["network"]
        self.set_title(1)

        center_layout = BorderLayout(self.menu_layout)
        center_layout.set_percent_constraints(0, 0, 47, 0)

        left_layout = center_layout.LEFT
        right_layout = center_layout.CENTER

        label_layout = GridLayout(left_layout)
        label_layout.set_pixel_constraints(rows, columns)
        label_layout.get_next_constraints()

        value_layout = GridLayout(right_layout)
        value_layout.set_pixel_constraints(rows, columns)
        value_layout.get_next_constraints()

        self.network_panel = Container(util, self.menu_layout)

        rect = pygame.Rect(self.menu_layout.x, self.menu_layout.y + 1,
                           self.menu_layout.w, self.menu_layout.h - 1)
        b = util.config[BACKGROUND][MENU_BGR_COLOR]
        bgr = Component(util, rect, 0, 0, self.menu_layout, bgr=b)
        bgr.name = "network.panel.bgr"
        self.network_panel.add_component(bgr)

        self.internet_label = self.add_label(label_layout, self.network_panel,
                                             1)
        self.ethernet_label = self.add_label(label_layout, self.network_panel,
                                             2)
        self.wifi_network_label = self.add_label(label_layout,
                                                 self.network_panel, 3)
        self.wifi_ip_label = self.add_label(label_layout, self.network_panel,
                                            4)
        if self.linux and self.config[USAGE][USE_BLUETOOTH]:
            self.bluetooth_label = self.add_label(label_layout,
                                                  self.network_panel, 5)

        self.internet = self.add_value(value_layout, self.network_panel, 1)
        self.ethernet_ip = self.add_value(value_layout, self.network_panel, 2)
        self.wifi_network = self.add_value(value_layout, self.network_panel, 3)
        self.wifi_ip = self.add_value(value_layout, self.network_panel, 4)
        if self.linux and self.config[USAGE][USE_BLUETOOTH]:
            self.bluetooth = self.add_value(value_layout, self.network_panel,
                                            5)

        self.add_component(self.network_panel)

        listeners[KEY_REFRESH] = self.set_current
        listeners[KEY_DISCONNECT] = self.disconnect_wifi
        listeners[KEY_BLUETOOTH_REMOVE] = self.remove_bluetooth_devices

        self.navigator = NetworkNavigator(self.util, self.layout.BOTTOM,
                                          listeners)
        self.navigator.components[0].set_selected(True)
        self.add_navigator(self.navigator)
        self.original_networks = None
        self.networks = None
        self.current_network = None
        self.current_wifi_network = None
        self.clicked = False
        Screen.link_borders(self, False)

    def set_current(self, state):
        """ Set current state

        :param state: button state
        """
        if state and getattr(state, "source", None) == "bluetooth":
            self.set_loading(self.title)
            self.bluetooth_util.connect_device(state.name, state.mac_address,
                                               True)
            self.set_initial_state(state)
            if self.bluetooth.text:
                self.bluetooth_util.update_asoundrc(OUTPUT_TYPE_BLUETOOTH,
                                                    state.mac_address)
            self.reset_loading()
            self.clean_draw_update()
            return

        if not state or (state and not getattr(state, KEY_CALLBACK_VAR, None)):
            self.set_loading(self.title)
            self.set_initial_state(state)
            self.reset_loading()
        else:
            self.connect_wifi(state)

        self.clean_draw_update()

    def set_initial_state(self, state):
        """ Set initial screen

        :param state: button state
        """
        info = self.get_network_info()

        self.internet_label.set_text("Internet:")
        self.ethernet_label.set_text("Ethernet IP:")
        self.wifi_network_label.set_text("Wi-Fi Network:")
        self.wifi_ip_label.set_text("Wi-Fi IP:")
        if self.linux and self.config[USAGE][USE_BLUETOOTH]:
            self.bluetooth_label.set_text("Bluetooth:")

        self.set_value(self.internet, info, CONNECTED)
        self.set_value(self.ethernet_ip, info, ETHERNET_IP)
        self.set_value(self.wifi_network, info, WIFI_NETWORK)
        self.set_value(self.wifi_ip, info, WIFI_IP)
        if self.linux and self.config[USAGE][USE_BLUETOOTH]:
            self.set_value(self.bluetooth, info, BLUETOOTH)

    def set_value(self, field, info, key):
        """ Set text in provided field

        :param field: text field
        :param info: info dictionary
        :param key: dictionary key
        """
        try:
            field.set_text(self.truncate(info[key]))
        except:
            field.set_text("")

    def get_network_info(self):
        """ Get network information

        :return: dictionary with network info
        """
        info = self.wifi_util.get_network()
        connected = self.check_internet_connectivity()
        if connected:
            info[CONNECTED] = self.config[LABELS]["connected"]
        else:
            info[CONNECTED] = self.config[LABELS]["disconnected"]

        info[BLUETOOTH] = ""
        d = self.bluetooth_util.get_connected_device()
        if d:
            info[BLUETOOTH] = d["name"]

        return info

    def truncate(self, s):
        """ Truncate string

        :param s: input string

        :return: truncated string
        """
        CHARS = 18
        if len(s) > CHARS:
            s = s[0:CHARS] + "..."
        return s

    def add_label(self, layout, parent, n):
        """ Add label component

        :param layout: label layout
        :param parent: parent container
        :param n: label number
        :return: label component
        """
        c = layout.get_next_constraints()
        fgr = self.util.config[COLORS][COLOR_BRIGHT]
        h = H_ALIGN_RIGHT
        v = V_ALIGN_BOTTOM
        f = int((c.height * 50) / 100)
        name = "label." + str(n)
        label = self.factory.create_output_text(name, c, (0, 0, 0, 0), fgr, f,
                                                h, v)
        parent.add_component(label)
        return label

    def add_value(self, layout, parent, n):
        """ Add value component

        :param layout: layout
        :param parent: parent container
        :param n: component number
        :return: value component
        """
        c = layout.get_next_constraints()
        fgr = self.util.config[COLORS][COLOR_CONTRAST]
        h = H_ALIGN_LEFT
        v = V_ALIGN_TOP
        f = int((c.height * 68) / 100)
        name = "value." + str(n)
        gap = int((c.height * 20) / 100)
        value = self.factory.create_output_text(name,
                                                c, (0, 0, 0, 0),
                                                fgr,
                                                f,
                                                halign=h,
                                                valign=v,
                                                shift_x=gap)
        parent.add_component(value)
        return value

    def set_current_wifi_network(self, net):
        """ Set current Wi-Fi network

        :param net: new network name
        """
        self.current_wifi_network = net

    def connect_wifi(self, state):
        """ Connect to Wi-Fi network

        :param state: button state
        """
        self.set_loading(self.title, self.config[LABELS][KEY_CONNECTING])

        if self.linux:
            self.connect_wifi_linux(state)
        else:
            self.connect_wifi_windows()

        self.check_network()
        self.set_initial_state(None)
        self.reset_loading()

    def connect_wifi_windows(self):
        """ Connect to Wi-Fi on Windows """

        self.wifi_util.connect_wifi_windows(self.current_wifi_network,
                                            self.current_wifi_network)
        time.sleep(4)

    def connect_wifi_linux(self, state):
        """" Connect to Wi-Fi on Linux

        :param state: button state
        """
        pswd = getattr(state, KEY_CALLBACK_VAR, None)
        if not pswd:
            return
        encrypted_pswd = self.wifi_util.encrypt_psk(self.current_wifi_network,
                                                    pswd)

        if not encrypted_pswd:
            return

        self.wifi_util.create_wpa_file(self.current_wifi_network,
                                       encrypted_pswd)
        time.sleep(10)

    def disconnect_wifi(self, state):
        """ Disconnect from Wi-Fi network

        :param state: button state
        """
        self.set_loading(self.title, self.config[LABELS][KEY_DISCONNECTING])
        self.wifi_util.disconnect_wifi()
        self.check_network()
        time.sleep(3)
        self.set_initial_state(None)
        self.reset_loading()
        self.clean_draw_update()

    def remove_bluetooth_devices(self, state):
        """ Remove bluetooth devices

        :param state: button state
        """
        self.set_loading(self.title)
        self.bluetooth_util.remove_devices()
        self.set_initial_state(state)
        if not self.bluetooth.text:
            self.bluetooth_util.update_asoundrc(OUTPUT_TYPE_DEFAULT)
        self.reset_loading()
        self.clean_draw_update()

    def check_network(self):
        """ Check Internet connectivity """

        self.util.connected_to_internet = self.check_internet_connectivity()
        self.set_modes()

    def handle_event(self, event):
        """ Event handler

        :param event: event to handle
        """
        if not self.visible or event.type == pygame.MOUSEMOTION: return

        mouse_events = [pygame.MOUSEBUTTONUP, pygame.MOUSEBUTTONDOWN]
        pos = None
        try:
            pos = event.pos
        except:
            pass

        if pos and event.type in mouse_events:
            if self.menu_layout.collidepoint(event.pos):
                if event.type == pygame.MOUSEBUTTONDOWN:
                    return

                self.go_home(None)
                self.redraw_observer()
            else:
                for b in self.navigator.components:
                    if b.bounding_box.collidepoint(event.pos):
                        b.set_selected(True)
                    else:
                        b.set_selected(False)
                    b.clean_draw_update()

        Container.handle_event(self, 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(update_observer, redraw_observer)
Ejemplo n.º 6
0
class InfoScreen(Container):
    """ Info screen. Shows file specific info and metadata """
    def __init__(self, util, listener):
        """ Initializer
        
        :param util: utility object
        :Param listener: screen listener
        """
        self.name = KEY_INFO
        self.util = util
        self.config = util.config
        self.factory = Factory(util)
        self.listener = listener

        self.bg = self.util.get_background(self.name)
        self.bgr_type = self.bg[0]
        self.bgr = self.bg[1]
        self.bgr_key = self.bg[5]

        self.screen_w = self.config[SCREEN_INFO][WIDTH]
        self.screen_h = self.config[SCREEN_INFO][HEIGHT]
        self.lines = 14
        font_vertical_percent = 6
        self.bounding_box = util.screen_rect
        Container.__init__(self,
                           util,
                           self.bounding_box,
                           background=self.bg[1],
                           content=self.bg[2],
                           image_filename=self.bg[3])

        font_size = int((font_vertical_percent * self.bounding_box.h) / 100)
        self.f = util.get_font(font_size)

        center_layout = BorderLayout(self.bounding_box)
        center_layout.set_percent_constraints(0, 0, 44, 0)

        left_layout = center_layout.LEFT
        right_layout = center_layout.CENTER

        label_layout = GridLayout(left_layout)
        label_layout.set_pixel_constraints(self.lines, 1)
        label_layout.get_next_constraints()
        bb1 = label_layout.get_next_constraints()

        value_layout = GridLayout(right_layout)
        value_layout.set_pixel_constraints(self.lines, 1)
        value_layout.get_next_constraints()
        bb2 = value_layout.get_next_constraints()

        title_bb = pygame.Rect(bb1.x, bb1.y, bb1.w + bb2.w, bb1.h)
        self.title = self.add_title(title_bb)

        label_layout.get_next_constraints()
        self.add_label(label_layout, 1, self.config[LABELS]["file.size"] + ":")
        self.add_label(label_layout, 2,
                       self.config[LABELS]["sample.rate"] + ":")
        self.add_label(label_layout, 3, self.config[LABELS]["channels"] + ":")
        self.add_label(label_layout, 4,
                       self.config[LABELS]["bits.per.sample"] + ":")
        self.add_label(label_layout, 5, self.config[LABELS]["bit.rate"] + ":")

        label_layout.get_next_constraints()
        self.add_label(label_layout, 6, self.config[LABELS][GENRE] + ":")
        self.add_label(label_layout, 7, self.config[LABELS][ARTIST] + ":")
        self.add_label(label_layout, 8, self.config[LABELS][ALBUM] + ":")
        self.add_label(label_layout, 9, self.config[LABELS][DATE] + ":")

        value_layout.get_next_constraints()
        self.filesize = self.add_value(value_layout, 1)
        self.sample_rate = self.add_value(value_layout, 2)
        self.channels = self.add_value(value_layout, 3)
        self.bits = self.add_value(value_layout, 4)
        self.bit_rate = self.add_value(value_layout, 5)

        value_layout.get_next_constraints()
        self.genre = self.add_value(value_layout, 6)
        self.artist = self.add_value(value_layout, 7)
        self.album = self.add_value(value_layout, 8)
        self.date = self.add_value(value_layout, 9)

        self.values = [
            self.filesize, self.sample_rate, self.channels, self.bits,
            self.bit_rate, self.genre, self.artist, self.album, self.date
        ]

    def add_title(self, bb):
        """ Add title component

        :param bb: bounding box

        :return: title component
        """
        fgr = self.util.config[COLORS][COLOR_CONTRAST]
        h = H_ALIGN_CENTER
        v = V_ALIGN_BOTTOM
        f = int((bb.height * 80) / 100)
        name = GENERATED_IMAGE + "title"
        shift = int(bb.h / 2)
        title = self.factory.create_output_text(name,
                                                bb, (0, 0, 0, 0),
                                                fgr,
                                                f,
                                                h,
                                                v,
                                                shift_y=-shift)
        self.add_component(title)

        return title

    def add_label(self, layout, n, label_name):
        """ Add label component

        :param layout: label layout
        :param n: label number
        :param label_name: label name
        """
        c = layout.get_next_constraints()
        fgr = self.util.config[COLORS][COLOR_BRIGHT]
        h = H_ALIGN_RIGHT
        v = V_ALIGN_BOTTOM
        f = int((c.height * 70) / 100)
        name = GENERATED_IMAGE + "label." + str(n)
        label = self.factory.create_output_text(name, c, (0, 0, 0, 0), fgr, f,
                                                h, v)
        label.set_text(label_name)
        self.add_component(label)

    def add_value(self, layout, n):
        """ Add value component

        :param layout: layout
        :param parent: parent container
        :param n: component number

        :return: value component
        """
        c = layout.get_next_constraints()
        fgr = self.util.config[COLORS][COLOR_CONTRAST]
        h = H_ALIGN_LEFT
        v = V_ALIGN_BOTTOM
        f = int((c.height * 70) / 100)
        name = GENERATED_IMAGE + "value." + str(n)
        gap = int((c.height * 20) / 100)
        value = self.factory.create_output_text(name,
                                                c, (0, 0, 0, 0),
                                                fgr,
                                                f,
                                                halign=h,
                                                valign=v,
                                                shift_x=gap)
        self.add_component(value)

        return value

    def set_current(self, state):
        """ Set info in current screen

        :param state: button state
        """
        meta = self.util.get_file_metadata()

        if not meta:
            self.title.set_text("")
            for v in self.values:
                v.set_text("")
            return

        self.set_value(self.title, meta, "filename", max_chars=MAX_CHARS_TITLE)
        self.set_value(self.filesize,
                       meta,
                       "filesize",
                       unit=self.config[LABELS]["bytes"])
        self.set_value(self.sample_rate,
                       meta,
                       "sample_rate",
                       unit=self.config[LABELS]["hz"])
        self.set_value(self.channels, meta, "channels")
        self.set_value(self.bits, meta, "bits_per_sample")
        self.set_value(self.bit_rate,
                       meta,
                       "bitrate",
                       unit=self.config[LABELS]["kbps"])
        self.set_value(self.genre, meta, GENRE)
        self.set_value(self.artist, meta, ARTIST)
        self.set_value(self.album, meta, ALBUM)
        self.set_value(self.date, meta, DATE)

    def set_value(self, field, meta, key, max_chars=MAX_CHARS, unit=None):
        """ Set text in provided field

        :param field: text field
        :param meta: meta dictionary
        :param key: dictionary key
        :param max_chars: maximum characters in the field
        :param unit: value unit
        """
        try:
            v = meta[key]
            if isinstance(v, numbers.Number):
                if key == "bitrate":
                    v = round(v / 1000)

                n = "{:,}".format(v).replace(",", " ")
                if unit:
                    n += " " + unit
                field.set_text(n)
            else:
                field.set_text(self.truncate(v, max_chars))
        except:
            field.set_text("")

    def truncate(self, s, max_chars):
        """ Truncate string

        :param s: input string
        :param max_chars: maximum string length

        :return: truncated string
        """
        if len(s) > max_chars:
            s = s[0:max_chars] + "..."
        return s

    def handle_event(self, event):
        """ Handle screen events

        :param event: event object
        """
        if (event.type == pygame.MOUSEBUTTONUP and event.button == 1) or \
            (event.type == USER_EVENT_TYPE and event.sub_type == SUB_TYPE_KEYBOARD and event.keyboard_key == pygame.K_ESCAPE):
            s = State()
            s.source = KEY_BACK
            self.listener(s)
            self.redraw_observer()

    def exit_screen(self):
        """ Exit screen """
        pass

    def add_screen_observer(self, redraw_observer):
        """ Add screen observer
        
        :param redraw_observer: observer to redraw the whole screen
        """
        self.redraw_observer = redraw_observer
Ejemplo n.º 7
0
    def __init__(self,
                 util,
                 title_key,
                 percent_bottom_height=0,
                 voice_assistant=None,
                 screen_title_name="screen_title",
                 create_dynamic_title=False,
                 title_layout=None,
                 title=None):
        """ Initializer
        
        :param util: utility object
        :param title_key: the resource bundle key for the screen title
        """
        Container.__init__(self, util)
        self.util = util
        factory = Factory(util)
        self.config = util.config
        self.bounding_box = util.screen_rect
        self.bgr = (0, 0, 0)
        self.layout = BorderLayout(util.screen_rect)
        self.layout.set_percent_constraints(PERCENT_TOP_HEIGHT,
                                            percent_bottom_height, 0, 0)
        self.voice_assistant = voice_assistant

        self.font_size = int((self.layout.TOP.h * PERCENT_TITLE_FONT) / 100.0)
        d = self.config[COLORS][COLOR_DARK_LIGHT]
        c = self.config[COLORS][COLOR_CONTRAST]

        t_layout = self.layout.TOP
        if title_layout:
            t_layout = title_layout

        if create_dynamic_title:
            self.screen_title = factory.create_dynamic_text(
                screen_title_name, t_layout, d, c, self.font_size)
        else:
            self.screen_title = factory.create_output_text(
                screen_title_name, t_layout, d, c, self.font_size)

        if title:
            self.screen_title.set_text(title)
        else:
            if title_key and len(title_key) > 0:
                try:
                    label = self.config[LABELS][title_key]
                    self.screen_title.set_text(label)
                except:
                    pass

        if voice_assistant:
            self.screen_title.add_select_listener(self.handle_voice_assistant)
            self.layout.TOP.w += 1
            self.voice_command = factory.create_output_text(
                "voice_command", self.layout.TOP, d, c, self.font_size)
            self.voice_command.add_select_listener(self.handle_voice_assistant)
            self.voice_assistant.add_text_recognized_listener(
                self.text_recognized)
            self.voice_assistant.assistant.add_start_conversation_listener(
                self.start_conversation)
            self.voice_assistant.assistant.add_stop_conversation_listener(
                self.stop_conversation)

        if voice_assistant and voice_assistant.is_running():
            self.title_selected = False
        else:
            self.title_selected = True

        self.draw_title_bar()
        self.player_screen = False
        self.update_web_observer = None
        self.update_web_title = None

        self.loading_listeners = []
        self.LOADING = util.config[LABELS][KEY_LOADING]
Ejemplo n.º 8
0
    def __init__(self, util):
        """ Initializer
        
        :param util: utility object
        """
        self.util = util
        self.config = util.config
        self.config_class = util.config_class
        self.color_web_bgr = self.config[COLORS][COLOR_WEB_BGR]
        color_logo = self.config[COLORS][COLOR_CONTRAST]
        color_status = self.config[COLORS][COLOR_LOGO]

        Container.__init__(self, util, background=self.color_web_bgr)
        self.bounding_box = util.screen_rect
        self.start_listeners = []
        factory = Factory(util)
        self.installed_release = self.config[RELEASE]
        self.installed_edition = self.installed_release[EDITION_NAME]
        self.installed_year = self.installed_release[RELEASE_YEAR]
        self.installed_month = self.installed_release[RELEASE_MONTH]
        self.installed_day = self.installed_release[RELEASE_DAY]

        layout = BorderLayout(self.bounding_box)
        layout.set_percent_constraints(0, PERCENT_FOOTER_HEIGHT, 0, 0)
        font_size = int((layout.BOTTOM.h * PERCENT_FOOTER_FONT) / 100.0)

        button = factory.create_image_button("peppy",
                                             bounding_box=layout.CENTER,
                                             bgr=self.color_web_bgr,
                                             image_size_percent=68,
                                             selected=False)
        x = layout.CENTER.w / 2 - button.components[1].content.get_size()[0] / 2
        y = layout.CENTER.h / 2 - button.components[1].content.get_size()[1] / 2
        button.components[1].content_x = x
        button.components[1].content_y = y
        self.add_component(button)

        layout.BOTTOM.y -= int((self.bounding_box.h * 5) / 100)
        layout.BOTTOM.h += 1

        if self.util.connected_to_internet and self.config[USAGE][
                USE_CHECK_FOR_UPDATES]:
            bottom_layout = GridLayout(layout.BOTTOM)
            bottom_layout.set_pixel_constraints(2, 1)
            line_top = bottom_layout.get_next_constraints()
            line_bottom = bottom_layout.get_next_constraints()
        else:
            line_top = layout.BOTTOM

        self.release = factory.create_output_text("installed",
                                                  line_top,
                                                  self.color_web_bgr,
                                                  color_logo,
                                                  font_size,
                                                  full_width=True,
                                                  valign=V_ALIGN_BOTTOM)
        self.add_component(self.release)

        if self.util.connected_to_internet and self.config[USAGE][
                USE_CHECK_FOR_UPDATES]:
            self.status = factory.create_output_text("status",
                                                     line_bottom,
                                                     self.color_web_bgr,
                                                     color_status,
                                                     font_size,
                                                     full_width=True,
                                                     valign=V_ALIGN_TOP)
            self.add_component(self.status)
            self.new_release = self.get_new_release()
Ejemplo n.º 9
0
    def __init__(self, util):
        """ Initializer
        
        :param util: utility object
        """
        self.util = util
        self.config = util.config
        self.config_class = util.config_class
        factory = Factory(util)
        self.name = "about.screen"

        self.color_web_bgr = self.config[COLORS][COLOR_WEB_BGR]
        color_logo = self.config[COLORS][COLOR_CONTRAST]
        color_status = self.config[COLORS][COLOR_LOGO]
        opacity = self.config[BACKGROUND][MENU_BGR_OPACITY]
        c = (self.color_web_bgr[0], self.color_web_bgr[1],
             self.color_web_bgr[2], opacity)

        cont = util.screen_rect
        img_filename = None
        bg = self.util.get_background("about", c)

        self.bgr_type = bg[0]
        if bg[2]:
            self.bgr = bg[1]
            cont = bg[2]
        else:
            self.bgr = (bg[1][0], bg[1][1], bg[1][2])

        img_filename = bg[3]
        self.bgr_key = bg[5]

        Container.__init__(self,
                           util,
                           bounding_box=util.screen_rect,
                           background=self.color_web_bgr,
                           content=cont,
                           image_filename=img_filename)

        self.start_listeners = []

        self.installed_release = self.config[RELEASE]
        self.installed_edition = self.installed_release[EDITION_NAME]
        self.installed_year = self.installed_release[RELEASE_YEAR]
        self.installed_month = self.installed_release[RELEASE_MONTH]
        self.installed_day = self.installed_release[RELEASE_DAY]

        layout = BorderLayout(self.bounding_box)
        layout.set_percent_constraints(0, PERCENT_FOOTER_HEIGHT, 0, 0)
        font_size = int((layout.BOTTOM.h * PERCENT_FOOTER_FONT) / 100.0)

        button = factory.create_image_button("peppy",
                                             bounding_box=layout.CENTER,
                                             bgr=bg[1],
                                             image_size_percent=68,
                                             selected=False)
        if bg[2]:
            button.parent_screen = bg[2]
        else:
            button.parent_screen = layout.CENTER
        x = layout.CENTER.w / 2 - button.components[1].content.get_size()[0] / 2
        y = layout.CENTER.h / 2 - button.components[1].content.get_size()[1] / 2
        button.components[1].content_x = x
        button.components[1].content_y = y
        self.add_component(button)

        bottom_bgr = pygame.Rect(layout.BOTTOM.x, layout.BOTTOM.y - 1,
                                 layout.BOTTOM.w, layout.BOTTOM.h + 2)
        comp = Component(self.util, bottom_bgr, bb=bottom_bgr, bgr=bg[1])
        comp.name = "txt.bgr"
        self.add_component(comp)

        text_layout = pygame.Rect(
            layout.BOTTOM.x, layout.BOTTOM.y - int(
                (self.bounding_box.h * 5) / 100), layout.BOTTOM.w,
            layout.BOTTOM.h)

        if self.util.connected_to_internet and self.config[USAGE][
                USE_CHECK_FOR_UPDATES]:
            bottom_layout = GridLayout(text_layout)
            bottom_layout.set_pixel_constraints(2, 1)
            line_top = bottom_layout.get_next_constraints()
            line_bottom = bottom_layout.get_next_constraints()
        else:
            line_top = text_layout

        transparent = (0, 0, 0, 0)
        self.release = factory.create_output_text("installed",
                                                  line_top,
                                                  transparent,
                                                  color_logo,
                                                  font_size,
                                                  full_width=True,
                                                  valign=V_ALIGN_BOTTOM)
        self.release.parent_screen = bg[2]
        if bg[2]:
            self.release.parent_screen = bg[2]
        else:
            self.release.parent_screen = line_top
        self.add_component(self.release)

        if self.util.connected_to_internet and self.config[USAGE][
                USE_CHECK_FOR_UPDATES]:
            self.status = factory.create_output_text("status",
                                                     line_bottom,
                                                     transparent,
                                                     color_status,
                                                     font_size,
                                                     full_width=True,
                                                     valign=V_ALIGN_TOP)
            self.status.parent_screen = bg[2]
            self.add_component(self.status)
            self.new_release = self.get_new_release()
Ejemplo n.º 10
0
class NetworkScreen(MenuScreen):
    """ Network 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.factory = Factory(util)
        self.check_internet_connectivity = listeners[KEY_CHECK_INTERNET]
        self.go_home = listeners[KEY_HOME]
        self.set_modes = listeners[KEY_SET_MODES]

        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 = [6, 1]
        MenuScreen.__init__(self,
                            util,
                            listeners,
                            6,
                            1,
                            voice_assistant,
                            d,
                            None,
                            page_in_title=False,
                            show_loading=False)
        self.title = self.config[LABELS]["network"]
        self.set_title(1)

        center_layout = BorderLayout(self.menu_layout)
        center_layout.set_percent_constraints(0, 0, 47, 0)

        left_layout = center_layout.LEFT
        right_layout = center_layout.CENTER

        label_layout = GridLayout(left_layout)
        label_layout.set_pixel_constraints(6, 1)
        label_layout.get_next_constraints()

        value_layout = GridLayout(right_layout)
        value_layout.set_pixel_constraints(6, 1)
        value_layout.get_next_constraints()

        self.network_panel = Container(util, self.menu_layout, (100, 0, 0))

        rect = pygame.Rect(self.menu_layout.x, self.menu_layout.y + 1,
                           self.menu_layout.w, self.menu_layout.h - 1)
        bgr = Component(util, rect, 0, 0, self.menu_layout, (0, 0, 0),
                        self.util.config[COLORS][COLOR_DARK])
        bgr.name = "network.panel.bgr"
        self.network_panel.add_component(bgr)

        self.internet_label = self.add_label(label_layout, self.network_panel,
                                             1)
        self.ethernet_label = self.add_label(label_layout, self.network_panel,
                                             2)
        self.wifi_network_label = self.add_label(label_layout,
                                                 self.network_panel, 3)
        self.wifi_ip_label = self.add_label(label_layout, self.network_panel,
                                            4)

        self.internet = self.add_value(value_layout, self.network_panel, 1)
        self.ethernet_ip = self.add_value(value_layout, self.network_panel, 2)
        self.wifi_network = self.add_value(value_layout, self.network_panel, 3)
        self.wifi_ip = self.add_value(value_layout, self.network_panel, 4)

        self.set_menu(self.network_panel)

        listeners[KEY_REFRESH] = self.set_current
        listeners[KEY_DISCONNECT] = self.disconnect_wifi

        self.navigator = NetworkNavigator(self.util, self.layout.BOTTOM,
                                          listeners)
        self.components.append(self.navigator)
        self.original_networks = None
        self.networks = None
        self.current_network = None
        self.current_wifi_network = None
        self.clicked = False

    def set_current(self, state):
        """ Set current state

        :param state: button state
        """
        if not state or (state and not getattr(state, KEY_CALLBACK_VAR, None)):
            self.set_loading(self.title)
            self.set_initial_state(state)
            self.reset_loading()
        else:
            self.connect_wifi(state)

        self.clean_draw_update()

    def set_initial_state(self, state):
        """ Set initial screen

        :param state: button state
        """
        info = self.get_network_info()

        self.internet_label.set_text("Internet:")
        self.ethernet_label.set_text("Ethernet IP:")
        self.wifi_network_label.set_text("Wi-Fi Network:")
        self.wifi_ip_label.set_text("Wi-Fi IP:")

        self.set_value(self.internet, info, CONNECTED)
        self.set_value(self.ethernet_ip, info, ETHERNET_IP)
        self.set_value(self.wifi_network, info, WIFI_NETWORK)
        self.set_value(self.wifi_ip, info, WIFI_IP)

    def set_value(self, field, info, key):
        """ Set text in provided field

        :param field: text field
        :param info: info dictionary
        :param key: dictionary key
        """
        try:
            field.set_text(info[key])
        except:
            field.set_text("")

    def get_network_info(self):
        """ Get network information

        :return: dictionary with network info
        """
        info = self.wifi_util.get_network()
        connected = self.check_internet_connectivity()
        if connected:
            info[CONNECTED] = self.config[LABELS]["connected"]
        else:
            info[CONNECTED] = self.config[LABELS]["disconnected"]
        return info

    def add_label(self, layout, parent, n):
        """ Add label component

        :param layout: label layout
        :param parent: parent container
        :param n: label number
        :return: label component
        """
        c = layout.get_next_constraints()
        fgr = self.util.config[COLORS][COLOR_BRIGHT]
        bgr = self.util.config[COLORS][COLOR_DARK]
        h = H_ALIGN_RIGHT
        v = V_ALIGN_BOTTOM
        f = int((c.height * 50) / 100)
        name = "label." + str(n)
        label = self.factory.create_output_text(name, c, bgr, fgr, f, h, v)
        parent.add_component(label)
        return label

    def add_value(self, layout, parent, n):
        """ Add value component

        :param layout: layout
        :param parent: parent container
        :param n: component number
        :return: value component
        """
        c = layout.get_next_constraints()
        fgr = self.util.config[COLORS][COLOR_BRIGHT]
        bgr = self.util.config[COLORS][COLOR_DARK]
        h = H_ALIGN_LEFT
        v = V_ALIGN_TOP
        f = int((c.height * 68) / 100)
        name = "value." + str(n)
        gap = int((c.height * 20) / 100)
        value = self.factory.create_output_text(name,
                                                c,
                                                bgr,
                                                fgr,
                                                f,
                                                halign=h,
                                                valign=v,
                                                shift_x=gap)
        parent.add_component(value)
        return value

    def set_current_wifi_network(self, net):
        """ Set current Wi-Fi network

        :param net: new network name
        """
        self.current_wifi_network = net

    def connect_wifi(self, state):
        """ Connect to Wi-Fi network

        :param state: button state
        """
        self.set_loading(self.title, self.config[LABELS][KEY_CONNECTING])

        if "win" in sys.platform:
            self.connect_wifi_windows()
        else:
            self.connect_wifi_linux(state)

        self.check_network()
        self.set_initial_state(None)
        self.reset_loading()

    def connect_wifi_windows(self):
        """ Connect to Wi-Fi on Windows """

        self.wifi_util.connect_wifi_windows(self.current_wifi_network,
                                            self.current_wifi_network)
        time.sleep(4)

    def connect_wifi_linux(self, state):
        """" Connect to Wi-Fi on Linux

        :param state: button state
        """
        pswd = getattr(state, KEY_CALLBACK_VAR, None)
        if not pswd:
            return
        encrypted_pswd = self.wifi_util.encrypt_psk(self.current_wifi_network,
                                                    pswd)

        if not encrypted_pswd:
            return

        self.wifi_util.create_wpa_file(self.current_wifi_network,
                                       encrypted_pswd)
        time.sleep(10)

    def disconnect_wifi(self, state):
        """ Disconnect from Wi-Fi network

        :param state: button state
        """
        self.set_loading(self.title, self.config[LABELS][KEY_DISCONNECTING])
        self.wifi_util.disconnect_wifi()
        self.check_network()
        time.sleep(3)
        self.set_initial_state(None)
        self.reset_loading()
        self.clean_draw_update()

    def check_network(self):
        """ Check Internet connectivity """

        self.util.connected_to_internet = self.check_internet_connectivity()
        self.set_modes()

    def handle_event(self, event):
        """ Event handler

        :param event: event to handle
        """
        if not self.visible: return

        pos = None
        try:
            pos = event.pos
        except:
            pass

        if (pos and event.type == pygame.MOUSEBUTTONDOWN and self.menu_layout.collidepoint(pos)) or \
                (event.type == USER_EVENT_TYPE and event.sub_type == SUB_TYPE_KEYBOARD and event.action == pygame.KEYDOWN and \
                event.keyboard_key == kbd_keys[KEY_SELECT]):
            self.clicked = True
        elif (pos and event.type == pygame.MOUSEBUTTONUP and self.menu_layout.collidepoint(pos) and self.clicked) or \
                (event.type == USER_EVENT_TYPE and event.sub_type == SUB_TYPE_KEYBOARD and event.action == pygame.KEYUP and \
                event.keyboard_key == kbd_keys[KEY_SELECT] and self.clicked):
            self.go_home(None)
            self.redraw_observer()
            self.clicked = False
        else:
            Container.handle_event(self, 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)
        for b in self.navigator.menu_buttons:
            self.add_button_observers(b, update_observer, redraw_observer)
Ejemplo n.º 11
0
class Screen(Container):
    """ Base class for all screens with menu and navigator """
    
    def __init__(self, util, title_key, percent_bottom_height=0, voice_assistant=None, screen_title_name="screen_title", 
        create_dynamic_title=False, title_layout=None, title=None, bgr=None):
        """ Initializer
        
        :param util: utility object
        :param title_key: the resource bundle key for the screen title
        """
        self.util = util
        self.factory = Factory(util)
        self.config = util.config
        self.bounding_box = util.screen_rect

        if title_key:
            self.name = title_key
        else:
            self.name = "tmp"

        bg = self.util.get_background(self.name, bgr)
        self.bgr_type = bg[0]
        self.bgr = bg[1]
        self.bgr_key = bg[5]
        Container.__init__(self, util, bounding_box=self.bounding_box, background=bg[1], content=bg[2], image_filename=bg[3])
        self.original_image_filename = None
        try:
            self.original_image_filename = bg[4].replace("\\", "/")
        except:
            pass

        self.layout = BorderLayout(util.screen_rect)
        self.layout.set_percent_constraints(PERCENT_TOP_HEIGHT, percent_bottom_height, 0, 0)
        self.voice_assistant = voice_assistant

        self.font_size = int((self.layout.TOP.h * PERCENT_TITLE_FONT)/100.0)
        b = self.config[BACKGROUND][HEADER_BGR_COLOR]
        c = self.config[COLORS][COLOR_CONTRAST]
        
        t_layout = self.layout.TOP
        if title_layout:
            t_layout = title_layout
        
        if create_dynamic_title:
            self.screen_title = self.factory.create_dynamic_text(screen_title_name, t_layout, b, c, self.font_size)
        else:
            self.screen_title = self.factory.create_output_text(screen_title_name, t_layout, b, c, self.font_size)
        
        if title:
            self.screen_title.set_text(title)
        else:    
            if title_key and len(title_key) > 0:
                try:
                    label = self.config[LABELS][title_key]
                    self.screen_title.set_text(label)
                except:
                    pass 
        
        if voice_assistant:
            self.screen_title.add_select_listener(self.handle_voice_assistant)
            self.layout.TOP.w += 1
            self.voice_command = self.factory.create_output_text("voice_command", self.layout.TOP, b, c, self.font_size)
            self.voice_command.add_select_listener(self.handle_voice_assistant)
            self.voice_assistant.add_text_recognized_listener(self.text_recognized)
            self.voice_assistant.assistant.add_start_conversation_listener(self.start_conversation)
            self.voice_assistant.assistant.add_stop_conversation_listener(self.stop_conversation)
        
        if voice_assistant and voice_assistant.is_running():
            self.title_selected = False
        else:
            self.title_selected = True
            
        self.draw_title_bar()        
        self.player_screen = False
        self.update_web_observer = None
        self.update_web_title = None

        self.loading_listeners = []
        self.LOADING = util.config[LABELS][KEY_LOADING]
        self.animated_title = False
    
    def add_component(self, c):
        """ Add screen component

        :param c: component to add
        """
        if c:
            c.set_parent_screen(self)
        Container.add_component(self, c)

    def draw_title_bar(self):
        """ Draw title bar on top of the screen """
        
        if len(self.components) != 0 and self.title_selected:
            self.add_component(self.voice_command)
            self.title_selected = False
        elif len(self.components) != 0 and not self.title_selected:
            self.add_component(self.screen_title)
            self.title_selected = True
        elif len(self.components) == 0 and self.title_selected:
            self.add_component(self.screen_title)
        elif len(self.components) == 0 and not self.title_selected:
            self.voice_command.set_text(self.config[LABELS][KEY_WAITING_FOR_COMMAND])
            self.add_component(self.voice_command)
            
    def handle_voice_assistant(self, state=None):
        """ Start/Stop voice assistant 
        
        :state: not used
        """
        if self.title_selected:
            self.voice_assistant.start()
        else:
            self.voice_assistant.stop()
    
    def text_recognized(self, text):
        """ Handle text recognized event 
        
        :text: recognized text
        """
        c = self.config[LABELS][KEY_VA_COMMAND] + " " + text
        self.voice_command.set_text(c)
        self.voice_command.clean_draw_update()
        time.sleep(self.config[VOICE_ASSISTANT][VOICE_COMMAND_DISPLAY_TIME])
        if self.update_web_title:
            self.update_web_title(self.voice_command)
        
    def start_conversation(self, event):
        """ Start voice conversation
        
        :event: not used
        """
        if self.visible: 
            self.voice_command.set_visible(True)
        self.voice_command.set_text_no_draw(self.config[LABELS][KEY_WAITING_FOR_COMMAND])
        self.components[0] = self.voice_command
        self.title_selected = False
        if self.visible:
            self.voice_command.clean_draw_update()
            if self.update_web_observer:
                self.update_web_observer()
    
    def stop_conversation(self):
        """ Stop voice conversation """
        
        if self.visible: 
            self.screen_title.set_visible(True)
        self.components[0] = self.screen_title
        self.title_selected = True
        if self.visible:
            self.screen_title.clean_draw_update()
            if self.update_web_observer:
                self.update_web_observer()
    
    def add_menu(self, menu):
        """ Add menu to the screen
        
        :param menu: the menu to add
        """
        self.menu = menu
        self.add_component(menu)

    def add_navigator(self, navigator):
        """ Add navigator to the screen
        
        :param menu: the menu to add
        """
        self.navigator = navigator
        self.add_component(navigator)

    def enable_player_screen(self, flag):
        """ Enable player screen
        
        :param flag: enable/disable flag
        """
        pass
    
    def exit_screen(self):
        """ Complete actions required to save screen state """
        
        self.set_visible(False)
    
    def add_screen_observers(self, update_observer, redraw_observer, title_to_json=None):
        """ Add screen observers.
        
        :param update_observer: observer for updating the screen
        :param redraw_observer: observer to redraw the whole screen
        """
        self.update_web_observer = redraw_observer
        self.update_web_title = title_to_json

    def set_loading(self, name=None, menu_bb=None, text=None):
        """ Show Loading... sign

        :param name: screen title
        :param menu_bb: menu bounding box
        :param text: screen text
        """
        b = self.config[BACKGROUND][MENU_BGR_COLOR]
        f = self.config[COLORS][COLOR_BRIGHT]
        fs = int(self.bounding_box.h * 0.07)

        if menu_bb != None:
            bb = menu_bb
        else:
            bb = self.bounding_box

        bb = Rect(bb.x, bb.y + 1, bb.w, bb.h - 1)

        t = self.factory.create_output_text(self.LOADING, bb, b, f, fs)
        if not text:
            t.set_text_no_draw(self.LOADING)
        else:
            t.set_text_no_draw(text)

        if name != None:
            self.screen_title.set_text(name)

        self.set_visible(True)
        self.add_component(t)
        if getattr(self, "menu", None) != None:
            self.menu.buttons = {}
            self.menu.components = []
        self.clean_draw_update()
        self.notify_loading_listeners()

    def reset_loading(self):
        """ Remove Loading label """

        del self.components[-1]
        self.notify_loading_listeners()

    def add_loading_listener(self, listener):
        """ Add loading listener

        :param listener: event listener
        """
        if listener not in self.loading_listeners:
            self.loading_listeners.append(listener)

    def notify_loading_listeners(self):
        """ Notify all loading listeners """

        for listener in self.loading_listeners:
            listener(None)

    def handle_event(self, event):
        """ Event handler

        :param event: event to handle
        """
        if not self.visible: return

        mouse_events = [pygame.MOUSEBUTTONUP, pygame.MOUSEBUTTONDOWN]
        
        if event.type in mouse_events and getattr(self, "menu", None) and getattr(self, "navigator", None):
            event_component = None

            for comp in self.menu.components:
                if getattr(comp, "state", None):
                    bb = comp.state.bounding_box
                else:
                    bb = comp.bounding_box

                if bb == None:
                    continue

                if bb.collidepoint(event.pos):
                    event_component = comp
                    for c in self.menu.components:
                        if hasattr(c, "set_selected") and c != comp:
                            c.set_selected(False)
                            c.clean_draw_update()

            if event_component:
                self.navigator.unselect()
                event_component.handle_event(event)
                if hasattr(self.menu, "current_slider"):
                    self.menu.current_slider = event_component.id
                if self.update_web_observer:
                    self.update_web_observer()
                return
            
            for comp in self.navigator.components:
                if getattr(comp, "state", None):
                    bb = comp.state.bounding_box
                else:
                    bb = comp.bounding_box

                if bb == None:
                    continue

                if bb.collidepoint(event.pos):
                    event_component = comp
                    break
            if event_component:
                for c in self.menu.components:
                    if getattr(c, "selected", False):
                        c.set_selected(False)
                        c.clean_draw_update()
                    elif hasattr(c, "slider"):
                        c.slider.set_knob_off()
                self.navigator.unselect()
                event_component.handle_event(event)
                if self.update_web_observer:
                    self.update_web_observer()
        else:
            Container.handle_event(self, event)
            self.update_web_observer()

    def get_menu_bottom_exit_xy(self, x):
        """ Get bottom exit coordinates

        :param x: event x coordinate
        """
        button = None
        xy = None
        for b in self.menu.components:
            if getattr(b, "bounding_box", None) == None:
                continue
            y = b.bounding_box.y + 5
            if b.bounding_box.collidepoint((x, y)):
                button = b

        if button == None:
            num = len(self.menu.components)
            if num != 0:
                button = self.menu.components[num - 1]
        
        if button != None and getattr(button, "bounding_box", None) != None:
            xy = (button.bounding_box.x + (button.bounding_box.w / 2), button.bounding_box.y)    

        return xy

    def link_borders(self, navigator_top_bottom_exit=True, first_index=None, last_index=None):
        """ Link components borders for the arrow keys navigation 

        :param navigator_top_bottom_exit:
        """
        if not hasattr(self.navigator, "components"):
            return

        margin = 10
        num = len(self.navigator.components)
        first_menu_comp = last_menu_comp = None

        if getattr(self, "menu", None):
            self.menu.exit_top_y = self.menu.exit_bottom_y = self.menu.bounding_box.y + self.menu.bounding_box.h + margin
            
            first_nav_comp = self.navigator.components[0]
            last_nav_comp = self.navigator.components[num - 1]

            self.menu.exit_right_x = first_nav_comp.bounding_box.x + margin
            self.menu.exit_right_y = first_nav_comp.bounding_box.y + margin
            
            self.menu.exit_left_x = last_nav_comp.bounding_box.x + last_nav_comp.bounding_box.w - margin
            self.menu.exit_left_y = last_nav_comp.bounding_box.y + margin

            if first_index == None: first_index = 0
            if last_index == None: last_index = len(self.menu.components) - 1
            if len(self.menu.components) > 0:
                first_menu_comp = self.menu.components[first_index]
                last_menu_comp = self.menu.components[last_index]

        if getattr(self, "menu", None) and len(self.menu.components) == 0:
            navigator_top_bottom_exit = False    

        for index, comp in enumerate(self.navigator.components):
            if navigator_top_bottom_exit and getattr(self, "menu", None):
                xy = self.get_menu_bottom_exit_xy(comp.bounding_box.x + 5)
                if xy:
                    comp.exit_top_y = xy[1] + margin
                    comp.exit_bottom_y = self.menu.bounding_box.y + margin
                    comp.exit_x = xy[0]
            else:
                comp.exit_top_y = None
                comp.exit_bottom_y = None
                comp.exit_x = None

            if index == 0:
                if last_menu_comp != None:
                    comp.exit_left_x = last_menu_comp.bounding_box.x + margin
                    comp.exit_left_y = last_menu_comp.bounding_box.y + margin
                else:
                    comp.exit_left_x = self.navigator.components[num - 1].bounding_box.x + margin
                    comp.exit_left_y = self.navigator.components[num - 1].bounding_box.y + margin
                c = self.navigator.components[index + 1]
                comp.exit_right_x = c.bounding_box.x + margin
            elif index == (num - 1):
                c = self.navigator.components[num - 2]
                comp.exit_left_x = c.bounding_box.x + margin
                if first_menu_comp != None:
                    comp.exit_right_x = first_menu_comp.bounding_box.x + margin
                    comp.exit_right_y = first_menu_comp.bounding_box.y + margin
                else:
                    comp.exit_right_x = self.navigator.components[0].bounding_box.x + margin
                    comp.exit_right_y = self.navigator.components[0].bounding_box.y + margin
            else:
                c = self.navigator.components[index - 1]
                comp.exit_left_x = c.bounding_box.x + margin
                c = self.navigator.components[index + 1]
                comp.exit_right_x = c.bounding_box.x + margin
Ejemplo n.º 12
0
class Screen(Container):
    """ Base class for all screens. Extends Container class """
    def __init__(self,
                 util,
                 title_key,
                 percent_bottom_height=0,
                 voice_assistant=None,
                 screen_title_name="screen_title",
                 create_dynamic_title=False,
                 title_layout=None,
                 title=None,
                 bgr=None):
        """ Initializer
        
        :param util: utility object
        :param title_key: the resource bundle key for the screen title
        """
        self.util = util
        self.factory = Factory(util)
        self.config = util.config
        self.bounding_box = util.screen_rect

        if title_key:
            self.name = title_key
        else:
            self.name = "tmp"

        bg = self.util.get_background(self.name, bgr)
        self.bgr_type = bg[0]
        self.bgr = bg[1]
        self.bgr_key = bg[5]
        Container.__init__(self,
                           util,
                           bounding_box=self.bounding_box,
                           background=bg[1],
                           content=bg[2],
                           image_filename=bg[3])
        self.original_image_filename = None
        try:
            self.original_image_filename = bg[4].replace("\\", "/")
        except:
            pass

        self.layout = BorderLayout(util.screen_rect)
        self.layout.set_percent_constraints(PERCENT_TOP_HEIGHT,
                                            percent_bottom_height, 0, 0)
        self.voice_assistant = voice_assistant

        self.font_size = int((self.layout.TOP.h * PERCENT_TITLE_FONT) / 100.0)
        b = self.config[BACKGROUND][HEADER_BGR_COLOR]
        c = self.config[COLORS][COLOR_CONTRAST]

        t_layout = self.layout.TOP
        if title_layout:
            t_layout = title_layout

        if create_dynamic_title:
            self.screen_title = self.factory.create_dynamic_text(
                screen_title_name, t_layout, b, c, self.font_size)
        else:
            self.screen_title = self.factory.create_output_text(
                screen_title_name, t_layout, b, c, self.font_size)

        if title:
            self.screen_title.set_text(title)
        else:
            if title_key and len(title_key) > 0:
                try:
                    label = self.config[LABELS][title_key]
                    self.screen_title.set_text(label)
                except:
                    pass

        if voice_assistant:
            self.screen_title.add_select_listener(self.handle_voice_assistant)
            self.layout.TOP.w += 1
            self.voice_command = self.factory.create_output_text(
                "voice_command", self.layout.TOP, b, c, self.font_size)
            self.voice_command.add_select_listener(self.handle_voice_assistant)
            self.voice_assistant.add_text_recognized_listener(
                self.text_recognized)
            self.voice_assistant.assistant.add_start_conversation_listener(
                self.start_conversation)
            self.voice_assistant.assistant.add_stop_conversation_listener(
                self.stop_conversation)

        if voice_assistant and voice_assistant.is_running():
            self.title_selected = False
        else:
            self.title_selected = True

        self.draw_title_bar()
        self.player_screen = False
        self.update_web_observer = None
        self.update_web_title = None

        self.loading_listeners = []
        self.LOADING = util.config[LABELS][KEY_LOADING]
        self.animated_title = False

    def add_component(self, c):
        """ Add screen component

        :param c: component to add
        """
        if c:
            c.set_parent_screen(self)
        Container.add_component(self, c)

    def draw_title_bar(self):
        """ Draw title bar on top of the screen """

        if len(self.components) != 0 and self.title_selected:
            self.add_component(self.voice_command)
            self.title_selected = False
        elif len(self.components) != 0 and not self.title_selected:
            self.add_component(self.screen_title)
            self.title_selected = True
        elif len(self.components) == 0 and self.title_selected:
            self.add_component(self.screen_title)
        elif len(self.components) == 0 and not self.title_selected:
            self.voice_command.set_text(
                self.config[LABELS][KEY_WAITING_FOR_COMMAND])
            self.add_component(self.voice_command)

    def handle_voice_assistant(self, state=None):
        """ Start/Stop voice assistant 
        
        :state: not used
        """
        if self.title_selected:
            self.voice_assistant.start()
        else:
            self.voice_assistant.stop()

    def text_recognized(self, text):
        """ Handle text recognized event 
        
        :text: recognized text
        """
        c = self.config[LABELS][KEY_VA_COMMAND] + " " + text
        self.voice_command.set_text(c)
        self.voice_command.clean_draw_update()
        time.sleep(self.config[VOICE_ASSISTANT][VOICE_COMMAND_DISPLAY_TIME])
        if self.update_web_title:
            self.update_web_title(self.voice_command)

    def start_conversation(self, event):
        """ Start voice conversation
        
        :event: not used
        """
        if self.visible:
            self.voice_command.set_visible(True)
        self.voice_command.set_text_no_draw(
            self.config[LABELS][KEY_WAITING_FOR_COMMAND])
        self.components[0] = self.voice_command
        self.title_selected = False
        if self.visible:
            self.voice_command.clean_draw_update()
            if self.update_web_observer:
                self.update_web_observer()

    def stop_conversation(self):
        """ Stop voice conversation """

        if self.visible:
            self.screen_title.set_visible(True)
        self.components[0] = self.screen_title
        self.title_selected = True
        if self.visible:
            self.screen_title.clean_draw_update()
            if self.update_web_observer:
                self.update_web_observer()

    def add_menu(self, menu):
        """ Add menu to the screen
        
        :param menu: the menu to add
        """
        self.menu = menu
        self.add_component(menu)

    def enable_player_screen(self, flag):
        """ Enable player screen
        
        :param flag: enable/disable flag
        """
        pass

    def exit_screen(self):
        """ Complete actions required to save screen state """

        self.set_visible(False)

    def add_screen_observers(self,
                             update_observer,
                             redraw_observer,
                             title_to_json=None):
        """ Add screen observers.
        
        :param update_observer: observer for updating the screen
        :param redraw_observer: observer to redraw the whole screen
        """
        self.update_web_observer = redraw_observer
        self.update_web_title = title_to_json

    def set_loading(self, name=None, menu_bb=None, text=None):
        """ Show Loading... sign

        :param name: screen title
        :param menu_bb: menu bounding box
        :param text: screen text
        """
        b = self.config[BACKGROUND][MENU_BGR_COLOR]
        f = self.config[COLORS][COLOR_BRIGHT]
        fs = int(self.bounding_box.h * 0.07)

        if menu_bb != None:
            bb = menu_bb
        else:
            bb = self.bounding_box

        bb = Rect(bb.x, bb.y + 1, bb.w, bb.h - 1)

        t = self.factory.create_output_text(self.LOADING, bb, b, f, fs)
        if not text:
            t.set_text_no_draw(self.LOADING)
        else:
            t.set_text_no_draw(text)

        if name != None:
            self.screen_title.set_text(name)

        self.set_visible(True)
        self.add_component(t)
        if getattr(self, "menu", None) != None:
            self.menu.buttons = {}
            self.menu.components = []
        self.clean_draw_update()
        self.notify_loading_listeners()

    def reset_loading(self):
        """ Remove Loading label """

        del self.components[-1]
        self.notify_loading_listeners()

    def add_loading_listener(self, listener):
        """ Add loading listener

        :param listener: event listener
        """
        if listener not in self.loading_listeners:
            self.loading_listeners.append(listener)

    def notify_loading_listeners(self):
        """ Notify all loading listeners """

        for listener in self.loading_listeners:
            listener(None)
Ejemplo n.º 13
0
class MenuScreen(Screen):
    """ Site Menu Screen. Base class for all book menu screens """
    def __init__(self,
                 util,
                 listeners,
                 rows,
                 columns,
                 voice_assistant,
                 d=None,
                 turn_page=None,
                 page_in_title=True):
        """ Initializer
        
        :param util: utility object
        :param listeners: file browser listeners
        :param rows: menu rows
        :param d: dictionary with menu button flags
        :param turn_page: turn page callback
        :param util: utility object
        """
        self.util = util
        self.config = util.config
        self.factory = Factory(util)
        self.bounding_box = self.config[SCREEN_RECT]
        self.player = None
        self.turn_page = turn_page
        self.page_in_title = page_in_title

        self.cache = Cache(self.util)
        self.layout = BorderLayout(self.bounding_box)
        self.layout.set_percent_constraints(PERCENT_TOP_HEIGHT,
                                            PERCENT_BOTTOM_HEIGHT, 0, 0)
        Screen.__init__(self, util, "", PERCENT_TOP_HEIGHT, voice_assistant,
                        "menu_screen_screen_title", True, self.layout.TOP)

        color_dark_light = self.config[COLORS][COLOR_DARK_LIGHT]
        self.menu_layout = self.layout.CENTER

        self.menu_button_layout = self.get_menu_button_layout(d)
        self.img_rect = self.menu_button_layout.image_rectangle

        listeners[GO_LEFT_PAGE] = self.previous_page
        listeners[GO_RIGHT_PAGE] = self.next_page

        try:
            self.navigator = BookNavigator(util, self.layout.BOTTOM, listeners,
                                           color_dark_light, d[4])
            Container.add_component(self, None)
            Container.add_component(self, self.navigator)
        except:
            Container.add_component(self, None)

        self.total_pages = 0
        self.current_page = 1
        self.menu = None

        self.loading_listeners = []
        self.LOADING = util.config[LABELS][KEY_LOADING]

    def get_menu_button_layout(self, d):
        """ Return menu button layout
        
        :param d: dictionary with menu button flags
        
        :return: menu button layout
        """
        s = State()
        s.show_img = True
        s.show_label = True
        button_w = int(self.menu_layout.w / d[1])
        button_h = int(self.menu_layout.h / d[0])
        label_padding = 2
        image_padding = 4
        try:
            self.show_author = d[2]
        except:
            self.show_author = False

        try:
            self.show_genre = d[3]
        except:
            self.show_genre = False

        s.bounding_box = Rect(0, 0, button_w, button_h)
        return MultiLineButtonLayout(s, label_padding, image_padding)

    def previous_page(self, state):
        """ Handle click on left button 
        
        :param state: button state object
        """
        if self.current_page == 1:
            return

        self.current_page -= 1
        if getattr(state, "select_last", False):
            self.components[1].selected_index = 0

        self.menu.current_page = self.current_page
        self.menu.selected_index = 0
        self.turn_page()

    def next_page(self, state):
        """ Handle click on right button 
        
        :param state: button state object
        """
        if self.total_pages <= 1 or self.total_pages == self.current_page:
            return

        self.current_page += 1

        if self.current_page > self.total_pages:
            self.current_page = self.total_pages

        self.menu.current_page = self.current_page
        self.menu.selected_index = 0
        self.turn_page()

    def set_menu(self, menu):
        """ Set menu 
        
        :param menu: menu object
        """
        self.menu = self.components[1] = menu

    def set_title(self, page_num):
        """ Set screen title 
        
        :param page_num: menu page number
        """
        if self.total_pages == 1 or not self.page_in_title:
            self.screen_title.set_text(self.title)
            return

        if len(str(page_num)) <= len(str(self.total_pages)):
            self.screen_title.set_text(self.title + " (" + str(page_num) + ")")

    def reset_title(self):
        """ Reset screen title """

        self.screen_title.set_text(self.title + " (" + str(self.current_page) +
                                   ")")

    def go_to_page(self, page_num):
        """ Handle go to page event 
        
        :param page_num: menu page number
        """
        n = int(page_num)
        if n > self.total_pages:
            n = self.total_pages
        if n == 0:
            n = 1
        self.current_page = n
        self.menu.current_page = self.current_page
        self.turn_page()

    def get_image_from_cache(self, url):
        """ Return image from cache
        
        :param url: image url
        
        :return: image
        """
        return self.cache.get_image(url)

    def put_image_to_cache(self, url, img):
        """ Put image into cache
        
        :param url: image url
        :param img: image
        """
        self.cache.cache_image(img, url)

    def set_button_image(self, b, icon, img_y=None):
        """ Set button image
        
        :param b: button
        :param icon: image
        :param img_y: image Y coordinate
        """
        bb = b.bounding_box
        comps = b.components
        im = comps[1]
        im.content = icon
        w = im.content.get_size()[0]
        h = im.content.get_size()[1]
        im.content_x = bb.x + (bb.width - w) / 2

        if img_y == None:
            img_area_height = bb.height - ((bb.height / LINES) * 2)
            img_y = bb.y + (img_area_height - h) / 2

        im.content_y = img_y
        self.components[1].clean_draw_update()

    def set_loading(self, name):
        """ Show Loading... sign
        
        :name: screen title
        """
        b = self.config[COLORS][COLOR_DARK]
        f = self.config[COLORS][COLOR_BRIGHT]
        fs = int(self.bounding_box.h * 0.07)
        bb = self.menu_layout
        t = self.factory.create_output_text(self.LOADING, bb, b, f, fs)
        t.set_text(self.LOADING)
        self.screen_title.set_text(name)
        self.set_visible(True)
        self.add_component(t)
        self.clean_draw_update()
        self.notify_loading_listeners()

    def reset_loading(self):
        """ Remove Loading... sign """

        del self.components[-1]
        self.notify_loading_listeners()

    def add_loading_listener(self, listener):
        """ Add loading listener
        
        :param listener: event listener
        """
        if listener not in self.loading_listeners:
            self.loading_listeners.append(listener)

    def notify_loading_listeners(self):
        """ Notify all loading listeners """

        for listener in self.loading_listeners:
            listener(None)