示例#1
0
    def second_scroll(self):
        self._clear()
        ticks = Gtk.Image.new_from_file(self._stage.media_path('ticks.png'))

        copy = ["Complete all of the ticks in a", "quest to unlock rewards."]
        text_widgets = self._get_text_widgets(copy)

        chest = Gtk.Image.new_from_file(
            self._stage.media_path('chest-open.png'))

        button = KanoButton('NEXT', color='orange')
        button.connect('clicked', cb_wrapper, self.third_scroll)

        ticks.set_margin_top(20)
        self._vbox.pack_start(ticks, False, False, 0)

        text_widgets[0].set_margin_top(40)
        for w in text_widgets:
            self._vbox.pack_start(w, False, False, 0)

        chest.set_margin_top(35)
        self._vbox.pack_start(chest, False, False, 0)

        button.set_margin_top(40)
        button.set_margin_left(80)
        button.set_margin_right(80)
        self._vbox.pack_start(button, False, False, 0)

        self.show_all()
示例#2
0
    def third_scroll(self):
        self._clear()

        heading = Gtk.Label('New quest')
        add_class(heading, 'scroll-heading')

        world = Gtk.Image.new_from_file(self._stage.media_path('world.png'))

        copy = [
            "Journey to Kano World",
        ]
        text_widgets = self._get_text_widgets(copy)

        button = KanoButton('OK', color='orange')
        button.connect('clicked', cb_wrapper, self._stage._ctl.next_stage)

        heading.set_margin_top(35)
        self._vbox.pack_start(heading, False, False, 0)

        world.set_margin_top(35)
        self._vbox.pack_start(world, False, False, 0)

        text_widgets[0].set_margin_top(40)
        for w in text_widgets:
            self._vbox.pack_start(w, False, False, 0)

        button.set_margin_top(40)
        button.set_margin_left(80)
        button.set_margin_right(80)
        self._vbox.pack_start(button, False, False, 0)

        self.show_all()
示例#3
0
    def third_scroll(self):
        self._clear()

        heading = Gtk.Label('New quest')
        add_class(heading, 'scroll-heading')

        world = Gtk.Image.new_from_file(self._stage.media_path('world.png'))

        copy = [
            "Journey to Kano World",
        ]
        text_widgets = self._get_text_widgets(copy)

        button = KanoButton('OK', color='orange')
        button.connect('clicked', cb_wrapper, self._stage._ctl.next_stage)

        heading.set_margin_top(35)
        self._vbox.pack_start(heading, False, False, 0)

        world.set_margin_top(35)
        self._vbox.pack_start(world, False, False, 0)

        text_widgets[0].set_margin_top(40)
        for w in text_widgets:
            self._vbox.pack_start(w, False, False, 0)

        button.set_margin_top(40)
        button.set_margin_left(80)
        button.set_margin_right(80)
        self._vbox.pack_start(button, False, False, 0)

        self.show_all()
示例#4
0
    def first_scroll(self):
        self._clear()
        copy = [
            "Quests are a series of tasks that you",
            "can complete on your Kano to get", "great rewards."
        ]
        text_widgets = self._get_text_widgets(copy)

        img_path = self._stage.media_path('chest-closed.png')
        chest = Gtk.Image.new_from_file(img_path)

        button = KanoButton('NEXT', color='orange')
        button.connect('clicked', cb_wrapper, self.second_scroll)

        text_widgets[0].set_margin_top(30)
        for w in text_widgets:
            self._vbox.pack_start(w, False, False, 0)

        chest.set_margin_top(60)
        self._vbox.pack_start(chest, False, False, 0)

        button.set_margin_top(70)
        button.set_margin_left(80)
        button.set_margin_right(80)
        self._vbox.pack_start(button, False, False, 0)

        self.show_all()
示例#5
0
    def second_scroll(self):
        self._clear()
        ticks = Gtk.Image.new_from_file(self._stage.media_path('ticks.png'))

        copy = [
            "Complete all of the ticks in a",
            "quest to unlock rewards."
        ]
        text_widgets = self._get_text_widgets(copy)

        chest = Gtk.Image.new_from_file(self._stage.media_path('chest-open.png'))

        button = KanoButton('NEXT', color='orange')
        button.connect('clicked', cb_wrapper, self.third_scroll)

        ticks.set_margin_top(20)
        self._vbox.pack_start(ticks, False, False, 0)

        text_widgets[0].set_margin_top(40)
        for w in text_widgets:
            self._vbox.pack_start(w, False, False, 0)

        chest.set_margin_top(35)
        self._vbox.pack_start(chest, False, False, 0)

        button.set_margin_top(40)
        button.set_margin_left(80)
        button.set_margin_right(80)
        self._vbox.pack_start(button, False, False, 0)

        self.show_all()
示例#6
0
    def first_scroll(self):
        self._clear()
        copy = [
            "Quests are a series of tasks that you",
            "can complete on your Kano to get",
            "great rewards."
        ]
        text_widgets = self._get_text_widgets(copy)

        img_path = self._stage.media_path('chest-closed.png')
        chest = Gtk.Image.new_from_file(img_path)

        button = KanoButton('NEXT', color='orange')
        button.connect('clicked', cb_wrapper, self.second_scroll)

        text_widgets[0].set_margin_top(30)
        for w in text_widgets:
            self._vbox.pack_start(w, False, False, 0)

        chest.set_margin_top(60)
        self._vbox.pack_start(chest, False, False, 0)

        button.set_margin_top(70)
        button.set_margin_left(80)
        button.set_margin_right(80)
        self._vbox.pack_start(button, False, False, 0)

        self.show_all()
示例#7
0
class AudioTemplate(Gtk.Box):
    """
    Template for audio screens
    """

    def __init__(self, img_path, title, description):
        Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL)

        if img_path:
            self.image = Gtk.Image.new_from_file(img_path)
            self.pack_start(self.image, False, False, 0)
        self.heading = Heading(title, description)

        icon_path = os.path.join(MEDIA_DIR, "play-sound.png")
        self.kano_button = KanoButton(text="PLAY SOUND", color="blue",
                                      icon_filename=icon_path)
        self.kano_button.pack_and_align()
        self.kano_button.set_margin_top(10)
        self.pack_start(self.heading.container, False, False, 0)
        self.pack_start(self.kano_button.align, False, False, 0)

        button_box = Gtk.ButtonBox(spacing=15)
        button_box.set_layout(Gtk.ButtonBoxStyle.CENTER)

        self.yes_button = KanoButton("YES")
        self.yes_button.set_sensitive(False)
        self.no_button = KanoButton("NO", color="red")
        self.no_button.set_sensitive(False)
        button_box.pack_start(self.yes_button, False, False, 0)
        button_box.pack_start(self.no_button, False, False, 0)
        button_box.set_margin_bottom(5)

        self.pack_start(button_box, False, False, 15)
示例#8
0
class AudioHintTemplate(TopImageTemplate):
    """
    Template for hints for audio setup
    """

    def __init__(self, img_path, title, description, kano_button_text,
                 hint_text=""):
        TopImageTemplate.__init__(self, img_path)

        self.heading = HintHeading(title, description, hint_text)
        self.pack_start(self.heading.container, False, False, 0)

        self.heading.description.set_margin_bottom(0)
        self.heading.container.set_margin_bottom(0)
        self.heading.container.set_size_request(590, -1)
        self.heading.container.set_spacing(0)

        self.kano_button = KanoButton(kano_button_text)
        self.kano_button.set_margin_top(30)
        self.kano_button.set_margin_bottom(30)
        self.kano_button.pack_and_align()

        self.pack_start(self.kano_button.align, False, False, 0)
class RegistrationScreen(Gtk.Box):
    """
    """
    def __init__(self, win):
        Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL)
        self.win = win
        self.win.set_main_widget(self)
        self.win.set_decorated(True)

        title = Heading(_("Kano World"),
                        _("Choose a cool name and secure password"))
        self.pack_start(title.container, False, False, 0)

        self.data_screen = GetData()  # TODO: refactor this
        self.data_screen.connect('widgets-filled',
                                 self._enable_register_button)
        self.data_screen.connect('widgets-empty',
                                 self._disable_register_button)
        self.add(self.data_screen)

        self.register_button = KanoButton(_("JOIN KANO WORLD"))
        self.register_button.set_sensitive(False)
        self.register_button.set_margin_top(10)
        self.register_button.set_margin_left(30)
        self.register_button.set_margin_right(30)
        self.register_button.set_margin_bottom(30)
        self.register_button.connect('clicked', self._on_register_button)
        self.pack_end(self.register_button, False, False, 0)

        self.win.show_all()

    def _enable_register_button(self, widget=None):
        """
        """
        self.register_button.set_sensitive(True)

    def _disable_register_button(self, widget=None):
        """
        """
        self.register_button.set_sensitive(False)

    def _on_register_button(self, widget=None):  # TODO: refactor this
        """
        """
        if not is_internet():
            self._show_not_internet_dialog()
            return

        # Get the username, password and birthday
        data = self.data_screen.get_widget_data()
        email = data['email']
        username = data['username']

        # Validate that the email address format is correct
        email_error = validate_email(email)
        if email_error:
            self._show_error_dialog(_("Incorrect Email address"), email_error)
            return

        if not self._is_username_available(username):
            self._show_username_taken_dialog(username)
            return

        # We can save the username to kano-profile
        # Don't save password as this is private
        self.data_screen.save_username_and_birthday()  # TODO: rename this
        self.data_screen.cache_emails()
        data = self.data_screen.get_widget_data()

        # This means no threads are needed.
        while Gtk.events_pending():  # TODO: why is this needed?
            Gtk.main_iteration()

        # Try and register the account on the server
        password = data['password']
        success, text = register_(email,
                                  username,
                                  password,
                                  marketing_enabled=True)

        # This should no longer be needed, since this is checked in the first
        # screen. However there is a small chance someone could take the
        # username while the user is in the process of registering
        if not success:
            if text.strip() == _("Cannot register, problem: "
                                 "Username already registered"):

                self._show_username_taken_dialog(username)

            else:
                logger.info("problem with registration: {}".format(text))
                return_value = 'FAIL'
                self._create_dialog(title=_("Houston, we have a problem"),
                                    description=str(text))
                track_data('world-registration-failed', {'reason': text})

        else:
            logger.info("registration successful")

            # saving hardware info and initial Kano version
            save_hardware_info()
            save_kano_version()

            # running kano-sync after registration
            logger.info("running kano-sync after successful registration")
            cmd = '{bin_dir}/kano-sync --sync -s'.format(bin_dir=bin_dir)
            run_bg(cmd)

            return_value = 'SUCCEED'
            self._create_dialog(
                title=_("Profile activated!"),
                description=_("Now you can share stuff, build your character, "
                              "and connect with friends."))

        self.win.get_window().set_cursor(None)

        # Close the app if it was successful
        if return_value == 'SUCCEED':
            Gtk.main_quit()

    def _is_username_available(self, name):
        """
        Returns True if username is available, and False otherwise
        """
        # Use the endpoint api.kano.me/users/username/:name
        success, text, data = request_wrapper(
            'get',
            '/users/username/{}'.format(name),
            headers=content_type_json)

        if not success and text.strip() == "User not found":
            return True
        elif success:
            # Username is definitely taken
            return False
        else:
            # Maybe let the user know something went wrong? e.g. if there's no
            # internet, launch a dialog at this point
            return False

    def _create_dialog(self, title, description):  # TODO: refactor this
        kdialog = KanoDialog(title, description, parent_window=self.win)
        rv = kdialog.run()
        return rv

    def _show_error_dialog(self, title, description):  # TODO: refactor this
        kdialog = KanoDialog(title, description, parent_window=self.win)
        kdialog.run()

    def _show_username_taken_dialog(self, username):  # TODO: refactor this
        track_data('world-registration-username-taken', {'username': username})
        kd = KanoDialog(_("This username is taken!"),
                        _("Try another one"),
                        parent_window=self.win)
        kd.run()
        self.data_screen.username.set_text("")
        self.data_screen.validate_username()
        self._disable_register_button()
        self.data_screen.username.grab_focus()

    def _show_not_internet_dialog(self):  # TODO: refactor this
        kd = KanoDialog(_("You don't have internet"),
                        _("Do you want to connect to WiFi?"),
                        [{
                            'label': _("YES"),
                            'color': 'green',
                            'return_value': 0
                        }, {
                            'label': _("NO"),
                            'color': 'red',
                            'return_value': 1
                        }],
                        parent_window=self.win)
        response = kd.run()

        # Close the dialog
        while Gtk.events_pending():  # TODO: why is this needed?
            Gtk.main_iteration()

        if response == 0:
            subprocess.Popen("sudo kano-wifi-gui", shell=True)
class RegistrationScreen(Gtk.Box):
    """
    """

    def __init__(self, win):
        Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL)
        self.win = win
        self.win.set_main_widget(self)
        self.win.set_decorated(True)

        title = Heading(
            _("Kano World"),
            _("Choose a cool name and secure password")
        )
        self.pack_start(title.container, False, False, 0)

        self.data_screen = GetData()  # TODO: refactor this
        self.data_screen.connect('widgets-filled', self._enable_register_button)
        self.data_screen.connect('widgets-empty', self._disable_register_button)
        self.add(self.data_screen)

        self.register_button = KanoButton(_("JOIN KANO WORLD"))
        self.register_button.set_sensitive(False)
        self.register_button.set_margin_top(10)
        self.register_button.set_margin_left(30)
        self.register_button.set_margin_right(30)
        self.register_button.set_margin_bottom(30)
        self.register_button.connect('clicked', self._on_register_button)
        self.pack_end(self.register_button, False, False, 0)

        self.win.show_all()

    def _enable_register_button(self, widget=None):
        """
        """
        self.register_button.set_sensitive(True)

    def _disable_register_button(self, widget=None):
        """
        """
        self.register_button.set_sensitive(False)

    def _on_register_button(self, widget=None):  # TODO: refactor this
        """
        """
        if not is_internet():
            self._show_not_internet_dialog()
            return

        # Get the username, password and birthday
        data = self.data_screen.get_widget_data()
        email = data['email']
        username = data['username']

        # Validate that the email address format is correct
        email_error = validate_email(email)
        if email_error:
            self._show_error_dialog(_("Incorrect Email address"), email_error)
            return

        if not self._is_username_available(username):
            self._show_username_taken_dialog(username)
            return

        # We can save the username to kano-profile
        # Don't save password as this is private
        self.data_screen.save_username_and_birthday()  # TODO: rename this
        self.data_screen.cache_emails()
        data = self.data_screen.get_widget_data()

        # This means no threads are needed.
        while Gtk.events_pending():  # TODO: why is this needed?
            Gtk.main_iteration()

        # Try and register the account on the server
        password = data['password']
        success, text = register_(email, username, password,
                                  marketing_enabled=True)

        # This should no longer be needed, since this is checked in the first
        # screen. However there is a small chance someone could take the
        # username while the user is in the process of registering
        if not success:
            if text.strip() == _("Cannot register, problem: "
               "Username already registered"):

                self._show_username_taken_dialog(username)

            else:
                logger.info("problem with registration: {}".format(text))
                return_value = 'FAIL'
                self._create_dialog(
                    title=_("Houston, we have a problem"),
                    description=str(text)
                )
                track_data('world-registration-failed', {'reason': text})

        else:
            logger.info("registration successful")

            # saving hardware info and initial Kano version
            save_hardware_info()
            save_kano_version()

            # running kano-sync after registration
            logger.info("running kano-sync after successful registration")
            cmd = '{bin_dir}/kano-sync --sync -s'.format(bin_dir=bin_dir)
            run_bg(cmd)

            return_value = 'SUCCEED'
            self._create_dialog(
                title=_("Profile activated!"),
                description=_("Now you can share stuff, build your character, "
                              "and connect with friends.")
            )

        self.win.get_window().set_cursor(None)

        # Close the app if it was successful
        if return_value == 'SUCCEED':
            Gtk.main_quit()

    def _is_username_available(self, name):
        """
        Returns True if username is available, and False otherwise
        """
        # Use the endpoint api.kano.me/users/username/:name
        success, text, data = request_wrapper(
            'get',
            '/users/username/{}'.format(name),
            headers=content_type_json
        )

        if not success and text.strip() == "User not found":
            return True
        elif success:
            # Username is definitely taken
            return False
        else:
            # Maybe let the user know something went wrong? e.g. if there's no
            # internet, launch a dialog at this point
            return False

    def _create_dialog(self, title, description):  # TODO: refactor this
        kdialog = KanoDialog(
            title,
            description,
            parent_window=self.win
        )
        rv = kdialog.run()
        return rv

    def _show_error_dialog(self, title, description):  # TODO: refactor this
        kdialog = KanoDialog(
            title,
            description,
            parent_window=self.win
        )
        kdialog.run()

    def _show_username_taken_dialog(self, username):  # TODO: refactor this
        track_data('world-registration-username-taken', {'username': username})
        kd = KanoDialog(
            _("This username is taken!"),
            _("Try another one"),
            parent_window=self.win
        )
        kd.run()
        self.data_screen.username.set_text("")
        self.data_screen.validate_username()
        self._disable_register_button()
        self.data_screen.username.grab_focus()

    def _show_not_internet_dialog(self):  # TODO: refactor this
        kd = KanoDialog(
            _("You don't have internet"),
            _("Do you want to connect to WiFi?"),
            [
                {
                    'label': _("YES"),
                    'color': 'green',
                    'return_value': 0
                },
                {
                    'label': _("NO"),
                    'color': 'red',
                    'return_value': 1
                }
            ],
            parent_window=self.win
        )
        response = kd.run()

        # Close the dialog
        while Gtk.events_pending():  # TODO: why is this needed?
            Gtk.main_iteration()

        if response == 0:
            subprocess.Popen("sudo kano-wifi-gui", shell=True)
示例#11
0
class BluetoothDeviceItem(Gtk.Box):
    __gsignals__ = {
        'pairing': (GObject.SIGNAL_RUN_FIRST, GObject.TYPE_NONE, ()),
        'done-pairing': (GObject.SIGNAL_RUN_FIRST, GObject.TYPE_NONE, ()),
    }

    def __init__(self, device):
        Gtk.Box.__init__(self, hexpand=True)

        self.device = device
        device_name = device.name

        dev_label = Gtk.Label(device_name, hexpand=True)
        dev_label.get_style_context().add_class('normal_label')
        self.pack_start(dev_label, False, False, 0)

        self._pair_button = KanoButton()
        self._set_paired_button_state()
        self._pair_button.set_margin_top(10)
        self._pair_button.set_margin_bottom(10)
        self._pair_button.set_margin_left(10)
        self._pair_button.set_margin_right(10)
        self._pair_button.connect('clicked', self.pair)
        self.pack_start(self._pair_button, False, False, 0)

    def _set_paired_button_state(self, *dummy_args, **dummy_kwargs):
        if not self.device.connected:
            label = _("PAIR")
            colour = 'green'
        else:
            label = _("UNPAIR")
            colour = 'red'

        self._pair_button.set_label(label)
        self._pair_button.set_color(colour)

    def error(self, err_msg):
        KanoDialog(err_msg).run()

    def pair(self, *dummy_args, **dummy_kwargs):
        def done_pairing():
            self._set_paired_button_state()
            self.emit('done-pairing')

        @queue_cb(callback=done_pairing, gtk=True)
        def do_pair():
            if not self.device.fuse():
                GObject.idle_add(self.error, _("Pairing failed"))

        @queue_cb(callback=done_pairing, gtk=True)
        def do_unpair():
            if not self.device.unfuse():
                GObject.idle_add(self.error, _("Unpairing failed"))

        self.emit('pairing')

        if self.device.connected:
            pair_fn = do_unpair
            logger.info("Unpairing {}".format(self.device))
        else:
            pair_fn = do_pair
            logger.info("Pairing {}".format(self.device))

        pair_thr = threading.Thread(target=pair_fn)
        pair_thr.start()
class BluetoothDeviceItem(Gtk.Box):
    __gsignals__ = {
        'pairing': (GObject.SIGNAL_RUN_FIRST, GObject.TYPE_NONE, ()),
        'done-pairing': (GObject.SIGNAL_RUN_FIRST, GObject.TYPE_NONE, ()),
    }

    def __init__(self, device):
        Gtk.Box.__init__(self, hexpand=True)

        self.device = device
        device_name = device.name

        dev_label = Gtk.Label(device_name, hexpand=True)
        dev_label.get_style_context().add_class('normal_label')
        self.pack_start(dev_label, False, False, 0)

        self._pair_button = KanoButton()
        self._set_paired_button_state()
        self._pair_button.set_margin_top(10)
        self._pair_button.set_margin_bottom(10)
        self._pair_button.set_margin_left(10)
        self._pair_button.set_margin_right(10)
        self._pair_button.connect('clicked', self.pair)
        self.pack_start(self._pair_button, False, False, 0)

    def _set_paired_button_state(self, *dummy_args, **dummy_kwargs):
        if not self.device.connected:
            label = _("PAIR")
            colour = 'green'
        else:
            label = _("UNPAIR")
            colour = 'red'

        self._pair_button.set_label(label)
        self._pair_button.set_color(colour)

    def error(self, err_msg):
        KanoDialog(err_msg).run()

    def pair(self, *dummy_args, **dummy_kwargs):
        def done_pairing():
            self._set_paired_button_state()
            self.emit('done-pairing')

        @queue_cb(callback=done_pairing, gtk=True)
        def do_pair():
            if not self.device.fuse():
                GObject.idle_add(self.error, _("Pairing failed"))

        @queue_cb(callback=done_pairing, gtk=True)
        def do_unpair():
            if not self.device.unfuse():
                GObject.idle_add(self.error, _("Unpairing failed"))

        self.emit('pairing')

        if self.device.connected:
            pair_fn = do_unpair
            logger.info("Unpairing {}".format(self.device))
        else:
            pair_fn = do_pair
            logger.info("Pairing {}".format(self.device))

        pair_thr = threading.Thread(target=pair_fn)
        pair_thr.start()
示例#13
0
    def __init__(self, stage, next_cb):
        super(Notebook, self).__init__()

        self.add(Gtk.Image.new_from_file(stage.media_path('notebook.png')))

        fixed = Gtk.Fixed()
        self.add_overlay(fixed)

        self._eb = Gtk.EventBox()
        add_class(self._eb, 'notebook-content-area')
        self._eb.set_size_request(425, 570)

        fixed.put(self._eb, 200, 90)

        vbox = Gtk.VBox(False, 0)
        vbox.set_vexpand(True)
        vbox.set_hexpand(True)
        vbox.set_margin_left(10)
        vbox.set_margin_right(10)

        heading = Gtk.Label('Screen machine')
        add_class(heading, 'heading')
        add_class(heading, 'notebook-heading')

        body_lines = [
            "Use the up and down arrows on the",
            "keyboard to adjust the picture until the",
            "screen pushing machine lines up with the",
            "edges of your TV."
        ]
        body_widgets = []
        for line in body_lines:
            body = Gtk.Label(line)
            body.set_line_wrap(False)
            body.set_justify(Gtk.Justification.LEFT)
            add_class(body, 'notebook-text')
            body.set_halign(Gtk.Align.START)
            body_widgets.append(body)

        # TODO: info
        legend_data = [
            {'icon': 'up-icon.png', 'desc': 'on your keyboard to increase'},
            {'icon': 'down-icon.png', 'desc': 'on your keyboard to decrease'},
            {'icon': 'ok-icon.png', 'desc': 'click the button to confirm'}
        ]
        legend_widgets = []
        for l in legend_data:
            legend = Gtk.HBox(False, 0)
            icon = Gtk.Image.new_from_file(stage.media_path(l['icon']))
            desc = Gtk.Label(l['desc'])
            add_class(desc, 'notebook-text')

            legend.pack_start(icon, False, False, 0)
            legend.pack_start(desc, False, False, 10)

            legend_widgets.append(legend)

        button = KanoButton('GO')
        button.connect('clicked', cb_wrapper, next_cb)

        # Pack heading
        vbox.pack_start(heading, False, False, 10)
        heading.set_margin_bottom(20)

        for w in body_widgets:
            vbox.pack_start(w, False, False, 8)

        legend_widgets[0].set_margin_top(30)
        for w in legend_widgets:
            vbox.pack_start(w, False, False, 10)

        button.set_margin_top(30)
        vbox.pack_start(button, False, False, 0)

        self._eb.add(vbox)