def _create_timed_alert(self, title, msg, timeout=10):
        alert = NotifyAlert(timeout)
        alert.props.title = title
        alert.props.msg = msg
        alert.connect('response', self._alert_cancel_cb)

        self.add_alert(alert)
 def _alert(self, title, msg=None):
     a = NotifyAlert()
     a.props.title = title
     a.props.msg = msg
     self.activity.add_alert(a)
     a.connect('response', lambda a, r: self.activity.remove_alert(a))
     a.show()
Exemple #3
0
    def _load_project(self, button):
        chooser = ObjectChooser(parent=self)
        result = chooser.run()
        if result == Gtk.ResponseType.ACCEPT:
            dsobject = chooser.get_selected_object()
            file_path = dsobject.get_file_path()
            try:
                f = open(file_path, 'r')
                # Test if the file is valid project.
                json.loads(f.read())
                f.close()

                self.read_file(file_path)
                self.game.run(True)
            except:
                title = _('Load project from journal')
                msg = _(
                    'Error: Cannot open Physics project from this file.')
                alert = NotifyAlert(5)
                alert.props.title = title
                alert.props.msg = msg
                alert.connect(
                    'response',
                    lambda alert,
                    response: self.remove_alert(alert))
                self.add_alert(alert)

            chooser.destroy()
Exemple #4
0
        def action(alert, response):
            self.remove_alert(alert)
            if not response is Gtk.ResponseType.OK:
                return

            try:
                f = open(file_path, 'r')
                # Test if the file is valid project.
                json.loads(f.read())
                f.close()

                self.read_file(file_path)
                self.game.run(True)
            except:
                title = _('Load project from journal')
                if not journal:
                    title = _('Load example')
                msg = _(
                    'Error: Cannot open Physics project from this file.')
                alert = NotifyAlert(5)
                alert.props.title = title
                alert.props.msg = msg
                alert.connect(
                    'response',
                    lambda alert,
                    response: self.remove_alert(alert))
                self.add_alert(alert)
Exemple #5
0
    def save_to_gsettings(self, icon=False, name=False):

        gsettings = Gio.Settings(_DESKTOP_CONF_DIR)
        homeviews = []

        for button in self._view_buttons:
            homeview = {'layout': 'ring-layout',
                        'view-icon': self._view_icons[button],
                        'favorite-icon': self._favorite_icons[button],
                        'view-label': self._favorite_names[button]}
            homeviews.append(homeview)

        variant = GLib.Variant('aa{ss}', homeviews)
        gsettings.set_value(_HOMEVIEWS_KEY, variant)
        if icon:
            for x in self.activity._alerts:
                self.activity.remove_alert(x)
            alert = NotifyAlert(5)
            alert.props.title = _('Icon')
            alert.props.msg = _('For see icons, restart sugar is needed.')
            self.activity.add_alert(alert)
            alert.connect('response',
                          lambda x, y: self.activity.remove_alert(x))
        if name:
            for x in self.activity._alerts:
                self.activity.remove_alert(x)
            alert = NotifyAlert(5)
            alert.props.title = _('View Name')
            alert.props.msg = _('For seeing View name changes, '
                                'restarting Sugar is required.')
            self.activity.add_alert(alert)
            alert.connect('response',
                          lambda x, y: self.activity.remove_alert(x))
 def _alert(self, title, text=None):
     alert = NotifyAlert(timeout=20)
     alert.props.title = title
     alert.props.msg = text
     self.add_alert(alert)
     alert.connect('response', self._alert_cancel_cb)
     alert.show()
Exemple #7
0
class _SharedJournalEntry(SharedJournalEntry):
    __gsignals__ = {
        'transfer-state-changed': (GObject.SignalFlags.RUN_FIRST, None,
                                   ([str, str])),
    }

    def __init__(self, account):
        self._account = account
        self._alert = None

    def get_share_menu(self, get_uid_list):
        menu = _ShareMenu(self._account, get_uid_list, True)
        self._connect_transfer_signals(menu)
        return menu

    def __display_alert_cb(self, widget, title, message):
        if self._alert is None:
            self._alert = NotifyAlert()
            self._alert.connect('response', self.__alert_response_cb)
            journalwindow.get_journal_window().add_alert(self._alert)
            self._alert.show()

        self._alert.props.title = title
        self._alert.props.msg = message

    def __alert_response_cb(self, alert, response_id):
        journalwindow.get_journal_window().remove_alert(alert)
        self._alert = None

    def _connect_transfer_signals(self, transfer_widget):
        transfer_widget.connect('transfer-state-changed',
                                self.__display_alert_cb)
Exemple #8
0
class _SharedJournalEntry(account.SharedJournalEntry):
    __gsignals__ = {
        'transfer-state-changed':
        (GObject.SignalFlags.RUN_FIRST, None, ([str])),
    }

    def __init__(self, account):
        self._account = account
        self._alert = None

    def get_share_menu(self, get_uid_list):
        menu = _ShareMenu(self._account, get_uid_list, True)
        self._connect_transfer_signals(menu)
        return menu

    def _connect_transfer_signals(self, transfer_widget):
        transfer_widget.connect('transfer-state-changed',
                                self.__display_alert_cb)

    def __display_alert_cb(self, widget, message):
        if self._alert is None:
            self._alert = NotifyAlert()
            self._alert.props.title = ACCOUNT_NAME
            self._alert.connect('response', self.__alert_response_cb)
            journalwindow.get_journal_window().add_alert(self._alert)
            self._alert.show()
        self._alert.props.msg = message

    def __alert_response_cb(self, alert, response_id):
        journalwindow.get_journal_window().remove_alert(alert)
        self._alert = None
 def _alert(self, title, msg=None):
     a = NotifyAlert()
     a.props.title = title
     a.props.msg = msg
     self.activity.add_alert(a)
     a.connect('response', lambda a, r: self.activity.remove_alert(a))
     a.show()
    def remove_confirmation(self, alert, response_id, path, cp_path,
            vbox, title):
        print cp_path, title
        if response_id == Gtk.ResponseType.OK:
            try:
                shutil.rmtree(path)
                shutil.rmtree(os.path.join(cp_path, title))
                alert_ = NotifyAlert(5)
                alert_.props.title = _('Removed')
                alert_.props.msg = _('Extension removed.'
                ' Please restart sugar for see efects')
                alert_.connect('response',
                    lambda x, y: self.activity.remove_alert(x))
                self.activity.add_alert(alert_)
                self.remove(vbox)
            except:
                alert_ = NotifyAlert(5)
                alert_.props.title = _('Error')
                alert_.props.msg = _('Error removing extension.')
                alert_.connect('response',
                    lambda x, y: self.activity.remove_alert(x))
                self.activity.add_alert(alert_)
        else:
            pass

        self.activity.remove_alert(alert)
Exemple #11
0
    def add_view(self, widget):
        if len(self._view_icons) >= 5:
            for x in self.activity._alerts:
                self.activity.remove_alert(x)
            alert = NotifyAlert(10)
            alert.props.title = _('Limit reached')
            alert.props.msg = _('You have reached the maximum limit of '
                                'favorites views, please delete some before '
                                'continuing.')
            self.activity.add_alert(alert)
            alert.connect('response',
                          lambda x, y: self.activity.remove_alert(x))
            return

        current = len(self._view_buttons) + 1
        label = _('Favorites view %d') % current
        button = ToolbarButton(label=label, icon_name='view-radial')
        page = FavoritePage(button, self, 'view-radial', 'emblem-favorite',
                            label)
        button.set_page(page)

        self._view_icons[button] = 'view-radial'
        self._favorite_icons[button] = 'emblem-favorite'
        self._view_buttons[button] = button
        self._favorite_names[button] = label

        self.insert(button, -1)
        self.save_to_gsettings()
        self.show_all()
Exemple #12
0
    def add_view(self, widget):
        if len(self._view_icons) >= 5:
            for x in self.activity._alerts:
                self.activity.remove_alert(x)
            alert = NotifyAlert(10)
            alert.props.title = _('Limit reached')
            alert.props.msg = _('You have reached the maximum limit of '
                                'favorites views, please delete some before '
                                'continuing.')
            self.activity.add_alert(alert)
            alert.connect('response',
                          lambda x, y: self.activity.remove_alert(x))
            return

        current = len(self._view_buttons) + 1
        label = _('Favorites view %d') % current
        button = ToolbarButton(label=label, icon_name='view-radial')
        page = FavoritePage(button, self, 'view-radial', 'emblem-favorite',
                            label)
        button.set_page(page)

        self._view_icons[button] = 'view-radial'
        self._favorite_icons[button] = 'emblem-favorite'
        self._view_buttons[button] = button
        if self.favorite_names_enabled:
            self._favorite_names[button] = label

        self.insert(button, -1)
        self.save_to_gconf()
        self.show_all()
Exemple #13
0
        def action(alert, response):
            self.remove_alert(alert)
            if response is not Gtk.ResponseType.OK:
                return

            try:
                f = open(file_path, 'r')
                # Test if the file is valid project.
                json.loads(f.read())
                f.close()

                self.read_file(file_path)
                self.game.run(True)
            except:
                title = _('Load project from journal')
                if not journal:
                    title = _('Load example')
                msg = _(
                    'Error: Cannot open Physics project from this file.')
                alert = NotifyAlert(5)
                alert.props.title = title
                alert.props.msg = msg
                alert.connect(
                    'response',
                    lambda alert,
                    response: self.remove_alert(alert))
                self.add_alert(alert)
Exemple #14
0
 def alert(self, title, text=None, timeout=5):
     if text != None:
         alert = NotifyAlert(timeout=timeout)
         alert.props.title = title
         alert.props.msg = text
         self.add_alert(alert)
         alert.connect('response', self.alert_cancel_cb)
         alert.show()
Exemple #15
0
 def alert(self, title, text=None, timeout=5):
     if text != None:
         alert = NotifyAlert(timeout=timeout)
         alert.props.title = title
         alert.props.msg = text
         self.add_alert(alert)
         alert.connect('response', self.cancel_alert)
         alert.show()
Exemple #16
0
class FacebookAccount(account.Account):

    ACCESS_TOKEN_KEY = "/desktop/sugar/collaboration/facebook_access_token"
    ACCESS_TOKEN_KEY_EXPIRATION_DATE = \
        "/desktop/sugar/collaboration/facebook_access_token_expiration_date"

    def __init__(self):
        self._client = GConf.Client.get_default()
        facebook.FbAccount.set_access_token(self._access_token())
        self._alert = None

    def get_description(self):
        return ACCOUNT_NAME

    def is_configured(self):
        return self._access_token() is not None

    def is_active(self):
        expiration_date = \
            self._client.get_int(self.ACCESS_TOKEN_KEY_EXPIRATION_DATE)
        return expiration_date != 0 and expiration_date > time.time()

    def get_share_menu(self, journal_entry_metadata):
        fb_share_menu = _FacebookShareMenu(journal_entry_metadata,
                                          self.is_active())
        self._connect_transfer_signals(fb_share_menu)
        return fb_share_menu

    def get_refresh_menu(self):
        fb_refresh_menu = _FacebookRefreshMenu(self.is_active())
        self._connect_transfer_signals(fb_refresh_menu)
        return fb_refresh_menu

    def _connect_transfer_signals(self, transfer_widget):
        transfer_widget.connect('transfer-state-changed',
                                self._transfer_state_changed_cb)

    def _transfer_state_changed_cb(self, widget, state_message):
        logging.debug('_transfer_state_changed_cb')

        # First, remove any existing alert
        if self._alert is None:
            logging.debug('creating new alert')
            self._alert = NotifyAlert()
            self._alert.props.title = ACCOUNT_NAME
            self._alert.connect('response', self._alert_response_cb)
            journalwindow.get_journal_window().add_alert(self._alert)
            self._alert.show()

        logging.debug(state_message)
        self._alert.props.msg = state_message

    def _alert_response_cb(self, alert, response_id):
        journalwindow.get_journal_window().remove_alert(alert)
        self._alert = None

    def _access_token(self):
        return self._client.get_string(self.ACCESS_TOKEN_KEY)
Exemple #17
0
 def _alert(self, title, text=None):
     alert = NotifyAlert(timeout=5)
     alert.props.title = title
     alert.props.msg = text
     self.add_alert(alert)
     alert.connect('response', self._alert_cancel_cb)
     alert.show()
     self._has_alert = True
     self._fixed_resize_cb()
Exemple #18
0
 def _alert(self, title, text=None):
     alert = NotifyAlert(timeout=5)
     alert.props.title = title
     alert.props.msg = text
     self.add_alert(alert)
     alert.connect('response', self._alert_cancel_cb)
     alert.show()
     self._has_alert = True
     self._fixed_resize_cb()
    def alert_time(self):
        def _alert_response_cb(alert, response_id):
            self.remove_alert(alert)

        alert = NotifyAlert()
        alert.props.title = _('Time Up!')
        alert.props.msg = _('Your time is up.')
        alert.connect('response', _alert_response_cb)
        alert.show()
        self.add_alert(alert)
Exemple #20
0
    def notify_alert(self, title, msg):
        """Raise standard notify alert"""
        alert = NotifyAlert(title=title, msg=msg)

        def response(alert, response_id, self):
            self.remove_alert(alert)

        alert.connect('response', response, self)
        alert.show_all()
        self.add_alert(alert)
    def alert_reset(self, mode):
        def _alert_response_cb(alert, response_id):
            self.remove_alert(alert)

        alert = NotifyAlert()
        alert.props.title = _('Time Reset')
        alert.props.msg = _('The timer mode was reset to %s' % mode)
        alert.connect('response', _alert_response_cb)
        alert.show()
        self.add_alert(alert)
Exemple #22
0
    def get_alert(self, title, text):
        """
        Show an alert above the activity.
        """

        alert = NotifyAlert(timeout=5)
        alert.props.title = title
        alert.props.msg = text
        self.add_alert(alert)
        alert.connect('response', self.__alert_cancel_cb)
        alert.show()
    def notify_alert(self):
        alert = NotifyAlert()
        alert.props.title = _('Saving icon...')
        msg = _('A restart is required before your new icon will appear.')
        alert.props.msg = msg

        def remove_alert(alert, response_id):
            self.remove_alert(alert)

        alert.connect('response', remove_alert)
        self.add_alert(alert)
 def internal_callback():
     try:
         urllib.urlretrieve(link, self.file_path,
             reporthook=self.progress_changed)
     except Exception, info:
         alert = NotifyAlert(5)
         alert.props.title = _('Error')
         alert.props.msg = info
         alert.connect('response',
             lambda x, y: self.activity.remove_alert(x))
         self.activity.add_alert(alert)
Exemple #25
0
    def notify_alert(self):
        alert = NotifyAlert()
        alert.props.title = _('Saving icon...')
        msg = _('A restart is required before your new icon will appear.')
        alert.props.msg = msg

        def remove_alert(alert, response_id):
            self.remove_alert(alert)

        alert.connect('response', remove_alert)
        self.add_alert(alert)
Exemple #26
0
 def _delete_log_cb(self, widget):
     if self.viewer.active_log:
         logfile = self.viewer.active_log.logfile
         try:
             os.remove(logfile)
         except OSError, err:
             notify = NotifyAlert()
             notify.props.title = _('Error')
             notify.props.msg = _('%(error)s when deleting %(file)s') % \
                 {'error': err.strerror, 'file': logfile}
             notify.connect('response', _notify_response_cb, self)
             self.add_alert(notify)
Exemple #27
0
 def _delete_log_cb(self, widget):
     if self.viewer.active_log:
         logfile = self.viewer.active_log.logfile
         try:
             os.remove(logfile)
         except OSError as err:
             notify = NotifyAlert()
             notify.props.title = _('Error')
             notify.props.msg = _('%(error)s when deleting %(file)s') % \
                 {'error': err.strerror, 'file': logfile}
             notify.connect('response', _notify_response_cb, self)
             self.add_alert(notify)
Exemple #28
0
    def _notify_new_game(self, prompt):
        ''' Called from New Game button since loading a new game can
        be slooow!! '''
        alert = NotifyAlert(3)
        alert.props.title = prompt
        alert.props.msg = _('A new game is loading.')

        def _notification_alert_response_cb(alert, response_id, self):
            self.remove_alert(alert)

        alert.connect('response', _notification_alert_response_cb, self)
        self.add_alert(alert)
        alert.show()
    def _confirm_save(self):
        color1 = self.colors[0].upper()
        color2 = self.colors[1].upper()

        settings = Gio.Settings("org.sugarlabs.user")
        settings.set_string("color", "%s,%s" % (color1, color2))

        alert = NotifyAlert()
        alert.props.title = _('Saving colors')
        alert.props.msg = _(
            'A restart is required before your new colors will appear.')
        alert.connect("response", self._notify_response_cb)
        self.add_alert(alert)
        alert.show_all()
    def _notify_alert(self, title='', msg='', action=None):
        def _notification_alert_response_cb(alert, response_id, self, action):
            self.remove_alert(alert)
            if action is not None:
                action()
            self._restore_cursor()

        alert = NotifyAlert()
        alert.props.title = title
        alert.connect('response', _notification_alert_response_cb, self,
                      action)
        alert.props.msg = msg
        self.add_alert(alert)
        alert.show()
    def _confirm_save(self):
        ''' Called from confirmation alert '''
        
        client.set_string('/desktop/sugar/user/color', '%s,%s' % (
                self._game.colors[0], self._game.colors[1]))
        alert = NotifyAlert()
        alert.props.title = _('Saving colors')
        alert.props.msg = _('A restart is required before your new colors '
                            'will appear.')

	def _notification_alert_response_cb(alert, response_id, self):
		self.remove_alert(alert)
        alert.connect('response', _notification_alert_response_cb, self)
        self.add_alert(alert)
        alert.show()
    def _notify_alert(self, title='', msg='', action=None):
        ''' Notify user when xfer is completed '''

        def _notification_alert_response_cb(alert, response_id, self, action):
            self.remove_alert(alert)
            if action is not None:
                action()

        alert = NotifyAlert()
        alert.props.title = title
        alert.connect('response', _notification_alert_response_cb, self,
                      action)
        alert.props.msg = msg
        self.add_alert(alert)
        alert.show()
Exemple #33
0
    def _create_image(self, text):
        fd = open('/tmp/cloud_data.txt', 'w')
        data = json_dump({
            'repeat': self._repeat_tags,
            'layout': self._layout,
            'font': self._font_name,
            'colors': self._color_scheme
        })
        fd.write(data)
        fd.close()
        fd = open('/tmp/cloud_text.txt', 'w')
        fd.write(text)
        fd.close()
        path = os.path.join('/tmp/cloud_large.png')
        try:
            subprocess.check_call(
                [os.path.join(activity.get_bundle_path(), 'wordcloud.py')])
        except subprocess.CalledProcessError as e:
            self.get_window().set_cursor(
                Gdk.Cursor.new(Gdk.CursorType.LEFT_PTR))
            alert = NotifyAlert(5)
            alert.props.title = _('WordCloud error')
            logging.error(e)
            logging.error(e.returncode)
            if e.returncode == 255:
                logging.error('STOP WORD ERROR')
                MESSAGE = _('All of your words are "stop words."'
                            ' Please try adding more words.')
            else:
                logging.error('MEMORY ERROR')
                MESSAGE = _('Oops. There was a problem. Please try again.')
            alert.props.msg = MESSAGE
            alert.connect('response', self._remove_alert_cb)
            self.add_alert(alert)
            return

        self.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.LEFT_PTR))

        self._show_image(path)

        dsobject = datastore.create()
        dsobject.metadata['title'] = _('Word Cloud')
        dsobject.metadata['icon-color'] = profile.get_color().to_string()
        dsobject.metadata['mime_type'] = 'image/png'
        dsobject.set_file_path(path)
        datastore.write(dsobject)
        dsobject.destroy()
Exemple #34
0
class _SharedJournalEntry(account.SharedJournalEntry):
    __gsignals__ = {
        'transfer-state-changed': (GObject.SignalFlags.RUN_FIRST, None,
                                   ([str])),
    }

    def __init__(self, fbaccount):
        self._account = fbaccount
        self._alert = None

    def get_share_menu(self, journal_entry_metadata):
        menu = _ShareMenu(
            self._account.facebook,
            journal_entry_metadata,
            self._account.get_token_state() == self._account.STATE_VALID)
        self._connect_transfer_signals(menu)
        return menu

    def get_refresh_menu(self):
        menu = _RefreshMenu(
            self._account.facebook,
            self._account.get_token_state() == self._account.STATE_VALID)
        self._connect_transfer_signals(menu)
        return menu

    def _connect_transfer_signals(self, transfer_widget):
        transfer_widget.connect('transfer-state-changed',
                                self._transfer_state_changed_cb)

    def _transfer_state_changed_cb(self, widget, state_message):
        logging.debug('_transfer_state_changed_cb')

        # First, remove any existing alert
        if self._alert is None:
            self._alert = NotifyAlert()
            self._alert.props.title = ACCOUNT_NAME
            self._alert.connect('response', self._alert_response_cb)
            journalwindow.get_journal_window().add_alert(self._alert)
            self._alert.show()

        logging.debug(state_message)
        self._alert.props.msg = state_message

    def _alert_response_cb(self, alert, response_id):
        journalwindow.get_journal_window().remove_alert(alert)
        self._alert = None
Exemple #35
0
    def _on_send_button_clicked_cb(self, button):
        window = self._activity.get_window()
        old_cursor = window.get_cursor()
        window.set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH))
        Gdk.flush()

        identifier = str(int(time.time()))
        filename = '%s.zip' % identifier
        filepath = os.path.join(activity.get_activity_root(), filename)
        success = True
        # FIXME: subprocess or thread
        try:
            self._collector.write_logs(archive=filepath, logbytes=0)
        except:
            success = False

        self.popdown(True)

        if not success:
            title = _('Logs not captured')
            msg = _('The logs could not be captured.')

            notify = NotifyAlert()
            notify.props.title = title
            notify.props.msg = msg
            notify.connect('response', _notify_response_cb, self._activity)
            self._activity.add_alert(notify)

        jobject = datastore.create()
        metadata = {
            'title': _('log-%s') % filename,
            'title_set_by_user': '******',
            'suggested_filename': filename,
            'mime_type': 'application/zip',
        }
        for k, v in metadata.items():
            jobject.metadata[k] = v
        jobject.file_path = filepath
        datastore.write(jobject)
        self._last_log = jobject.object_id
        jobject.destroy()
        activity.show_object_in_journal(self._last_log)
        os.remove(filepath)

        window.set_cursor(old_cursor)
        Gdk.flush()
Exemple #36
0
    def _on_send_button_clicked_cb(self, button):
        window = self._activity.get_window()
        old_cursor = window.get_cursor()
        window.set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH))
        Gdk.flush()

        identifier = str(int(time.time()))
        filename = '%s.zip' % identifier
        filepath = os.path.join(activity.get_activity_root(), filename)
        success = True
        # FIXME: subprocess or thread
        try:
            self._collector.write_logs(archive=filepath, logbytes=0)
        except BaseException:
            success = False

        self.popdown(True)

        if not success:
            title = _('Logs not captured')
            msg = _('The logs could not be captured.')

            notify = NotifyAlert()
            notify.props.title = title
            notify.props.msg = msg
            notify.connect('response', _notify_response_cb, self._activity)
            self._activity.add_alert(notify)

        jobject = datastore.create()
        metadata = {
            'title': _('log-%s') % filename,
            'title_set_by_user': '******',
            'suggested_filename': filename,
            'mime_type': 'application/zip',
        }
        for k, v in list(metadata.items()):
            jobject.metadata[k] = v
        jobject.file_path = filepath
        datastore.write(jobject)
        self._last_log = jobject.object_id
        jobject.destroy()
        activity.show_object_in_journal(self._last_log)
        os.remove(filepath)

        window.set_cursor(old_cursor)
        Gdk.flush()
    def _confirm_save(self):
        ''' Called from confirmation alert '''

        client.set_string(
            '/desktop/sugar/user/color',
            '%s,%s' % (self._game.colors[0], self._game.colors[1]))
        alert = NotifyAlert()
        alert.props.title = _('Saving colors')
        alert.props.msg = _(
            'A restart is required before your new colors will appear.')

        def _notification_alert_response_cb(alert, response_id, self):
            self.remove_alert(alert)

        alert.connect('response', _notification_alert_response_cb, self)
        self.add_alert(alert)
        alert.show()
Exemple #38
0
    def _create_image(self, text):
        fd = open('/tmp/cloud_data.txt', 'w')
        data = json_dump({'repeat': self._repeat_tags,
                          'layout': self._layout,
                          'font': self._font_name,
                          'colors': self._color_scheme})
        fd.write(data)
        fd.close()
        fd = open('/tmp/cloud_text.txt', 'w')
        fd.write(text)
        fd.close()
        path = os.path.join('/tmp/cloud_large.png')
        try:
            subprocess.check_call(
                [os.path.join(activity.get_bundle_path(), 'wordcloud.py')])
        except subprocess.CalledProcessError as e:
            self.get_window().set_cursor(
                Gdk.Cursor.new(Gdk.CursorType.LEFT_PTR))
            alert = NotifyAlert(5)
            alert.props.title = _('WordCloud error')
            logging.error(e)
            logging.error(e.returncode)
            if e.returncode == 255:
                logging.error('STOP WORD ERROR')
                MESSAGE = _('All of your words are "stop words."'
                            ' Please try adding more words.')
            else:
                logging.error('MEMORY ERROR')
                MESSAGE = _('Oops. There was a problem. Please try again.')
            alert.props.msg = MESSAGE
            alert.connect('response', self._remove_alert_cb)
            self.add_alert(alert)
            return

        self.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.LEFT_PTR))

        self._show_image(path)

        dsobject = datastore.create()
        dsobject.metadata['title'] = _('Word Cloud')
        dsobject.metadata['icon-color'] = profile.get_color().to_string()
        dsobject.metadata['mime_type'] = 'image/png'
        dsobject.set_file_path(path)
        datastore.write(dsobject)
        dsobject.destroy()
Exemple #39
0
    def save_to_gconf(self, icon=False, name=False):

        view_icons = []
        favorite_icons = []
        favorite_names = []

        for button in self._view_buttons:
            view_icons.append(self._view_icons[button])
            favorite_icons.append(self._favorite_icons[button])
            if self.favorite_names_enabled:
                favorite_names.append(self._favorite_names[button])

        client = GConf.Client.get_default()
        SugarExt.gconf_client_set_string_list(client,
                                              _FAVORITE_KEY,
                                              favorite_icons)

        SugarExt.gconf_client_set_string_list(client,
                                              _VIEW_KEY,
                                              view_icons)

        if self.favorite_names_enabled:
            SugarExt.gconf_client_set_string_list(client,
                                                  _FAVORITE_NAME_KEY,
                                                  favorite_names)

        if icon:
            for x in self.activity._alerts:
                self.activity.remove_alert(x)
            alert = NotifyAlert(5)
            alert.props.title = _('Icon')
            alert.props.msg = _('For see icons, restart sugar is needed.')
            self.activity.add_alert(alert)
            alert.connect('response',
                          lambda x, y: self.activity.remove_alert(x))
        if name:
            for x in self.activity._alerts:
                self.activity.remove_alert(x)
            alert = NotifyAlert(5)
            alert.props.title = _('View Name')
            alert.props.msg = _('For seeing View name changes, '
                                'restarting Sugar is required.')
            self.activity.add_alert(alert)
            alert.connect('response',
                          lambda x, y: self.activity.remove_alert(x))
Exemple #40
0
            def async_copy_activity_tree():
                try:
                    shutil.copytree(self._document_path,
                                    os.path.join(user_activities_path,
                                                 new_basename),
                                    symlinks=True)
                    customizebundle.generate_bundle(nick, new_basename)

                    if copy_alert:
                        self.get_toplevel().remove_alert(copy_alert)

                    alert = NotifyAlert(10)
                    alert.props.title = _('Duplicated')
                    alert.props.msg = _('The activity has been duplicated')
                    alert.connect('response', self.__alert_response_cb)
                    self.get_toplevel().add_alert(alert)
                finally:
                    self.__set_busy_cursor(False)
Exemple #41
0
    def __copy_to_home_cb(self, menu_item, copy_alert=None):
        """Make a local copy of the activity bundle in user_activities_path"""
        user_activities_path = get_user_activities_path()
        nick = customizebundle.generate_unique_id()
        new_basename = '%s_copy_of_%s' % (
            nick, os.path.basename(self._document_path))
        if not os.path.exists(os.path.join(user_activities_path,
                                           new_basename)):
            self.__set_busy_cursor(True)

            def async_copy_activity_tree():
                try:
                    shutil.copytree(self._document_path,
                                    os.path.join(
                                        user_activities_path,
                                        new_basename),
                                    symlinks=True)
                    customizebundle.generate_bundle(nick, new_basename)

                    if copy_alert:
                        self.get_toplevel().remove_alert(copy_alert)

                    alert = NotifyAlert(10)
                    alert.props.title = _('Duplicated')
                    alert.props.msg = _('The activity has been duplicated')
                    alert.connect('response', self.__alert_response_cb)
                    self.get_toplevel().add_alert(alert)
                finally:
                    self.__set_busy_cursor(False)

            GLib.idle_add(async_copy_activity_tree)
        else:
            if copy_alert:
                self.get_toplevel().remove_alert(copy_alert)

            self.__set_busy_cursor(False)

            alert = NotifyAlert(10)
            alert.props.title = _('Duplicated activity already exists')
            alert.props.msg = _('Delete your copy before trying to duplicate'
                                ' the activity again')

            alert.connect('response', self.__alert_response_cb)
            self.get_toplevel().add_alert(alert)
Exemple #42
0
    def __copy_to_home_cb(self, menu_item, copy_alert=None):
        """Make a local copy of the activity bundle in user_activities_path"""
        user_activities_path = get_user_activities_path()
        nick = customizebundle.generate_unique_id()
        new_basename = '%s_copy_of_%s' % (
            nick, os.path.basename(self._document_path))
        if not os.path.exists(os.path.join(user_activities_path,
                                           new_basename)):
            self.__set_busy_cursor(True)

            def async_copy_activity_tree():
                try:
                    shutil.copytree(self._document_path,
                                    os.path.join(
                                        user_activities_path,
                                        new_basename),
                                    symlinks=True)
                    customizebundle.generate_bundle(nick, new_basename)

                    if copy_alert:
                        self.get_toplevel().remove_alert(copy_alert)

                    alert = NotifyAlert(10)
                    alert.props.title = _('Duplicated')
                    alert.props.msg = _('The activity has been duplicated')
                    alert.connect('response', self.__alert_response_cb)
                    self.get_toplevel().add_alert(alert)
                finally:
                    self.__set_busy_cursor(False)

            GLib.idle_add(async_copy_activity_tree)
        else:
            if copy_alert:
                self.get_toplevel().remove_alert(copy_alert)

            self.__set_busy_cursor(False)

            alert = NotifyAlert(10)
            alert.props.title = _('Duplicated activity already exists')
            alert.props.msg = _('Delete your copy before trying to duplicate'
                                ' the activity again')

            alert.connect('response', self.__alert_response_cb)
            self.get_toplevel().add_alert(alert)
Exemple #43
0
            def async_copy_activity_tree():
                try:
                    shutil.copytree(self._document_path,
                                    os.path.join(
                                        user_activities_path,
                                        new_basename),
                                    symlinks=True)
                    customizebundle.generate_bundle(nick, new_basename)

                    if copy_alert:
                        self.get_toplevel().remove_alert(copy_alert)

                    alert = NotifyAlert(10)
                    alert.props.title = _('Duplicated')
                    alert.props.msg = _('The activity has been duplicated')
                    alert.connect('response', self.__alert_response_cb)
                    self.get_toplevel().add_alert(alert)
                finally:
                    self.__set_busy_cursor(False)
    def check_md5sum(self):
        md5sum = commands.getoutput('md5sum %s' % self.file_path)
        md5sum = md5sum.split()[0]
        if md5sum == self.md5sum:
            alert = NotifyAlert(10)
            alert.props.title = _('Downloaded')
            alert.props.msg = _('The extension has been downloaded'
                ' and installed.')
            for alert_ in self.activity._alerts:
                self.activity.remove_alert(alert_)
            alert.connect('response',
                lambda x, y: self.activity.remove_alert(x))
            self.activity.add_alert(alert)
            os.chdir(os.path.join(env.get_profile_path()))
            os.system('tar -xf %s' % self.file_path)

            window = self.get_window()
            window.set_cursor(None)
            GObject.source_remove(self.gobject_id)

        return True
    def open_from_journal(self):
        chooser = ObjectChooser()
        result = chooser.run()
        alert = NotifyAlert(5)
        if result == Gtk.ResponseType.ACCEPT:
            jobject = chooser.get_selected_object()
            if jobject and jobject.file_path:
                os.chdir(env.get_profile_path())
                output = commands.getoutput('tar -xf %s' % jobject.file_path)
                if 'end' in output or 'error' in output:
                    alert.props.title = _('Error')
                    alert.props.msg = _('Error extracting the extension.')
                else:
                    alert.props.title = _('Sucess')
                    alert.props.msg = _('The extension has been installed.')
            else:
                    alert.props.title = _('Error')
                    alert.props.msg = _('Error extracting the extension.')

        self.add_alert(alert)
        alert.connect('response', lambda x, y: self.remove_alert(x))
Exemple #46
0
def publish(activity, force=False):
    if not [i for i in book.custom.index if i['ready']]:
        alert = NotifyAlert(5)
        alert.props.title = _('Nothing to publish')
        alert.props.msg = _('Mark arcticles from "Custom" '
                            'panel and try again.')
        alert.connect('response', __alert_notify_response_cb, activity)
        activity.add_alert(alert)
        alert.show()
        return

    title = activity.metadata['title']
    jobject = datastore.find({
        'activity_id': activity.get_id(),
        'activity': book.custom.uid
    })[0] or None

    logger.debug('publish: title=%s jobject=%s force=%s' \
            % (title, jobject and jobject[0].metadata['activity'], force))

    if jobject:
        if force:
            jobject = jobject[0]
        else:
            alert = ConfirmationAlert()
            alert.props.title = _('Overwrite existed bundle?')
            alert.props.msg = _(
                'A bundle for current object was already created. '
                'Click "OK" to overwrite it.')
            alert.connect('response', __alert_response_cb, activity, True)
            activity.add_alert(alert)
            alert.show()
            jobject[0].destroy()
            return
    else:
        jobject = datastore.create()
        jobject.metadata['activity_id'] = activity.get_id()
        jobject.metadata['activity'] = book.custom.uid
        jobject.metadata['mime_type'] = 'application/vnd.olpc-content'
        jobject.metadata['description'] = \
                'This is a bundle containing articles on %s.\n' \
                'To view these articles, open the \'Browse\' Activity.\n' \
                'Go to \'Books\', and select \'%s\'.' % (title, title)

    book.custom.sync_article()
    book.custom.revision += 1

    jobject.metadata['title'] = title
    _publish(title, jobject)
    jobject.destroy()

    book.custom.sync_index()

    alert = NotifyAlert()
    alert.props.title = _('Book published to your Journal')
    alert.props.msg = _('You can read the book in Browse or '
                        'access the .xol file from your Journal')
    alert.connect('response', __alert_notify_response_cb, activity)
    activity.add_alert(alert)
    alert.show()
Exemple #47
0
def publish(activity, force=False):
    if not [i for i in book.custom.index if i['ready']]:
        alert = NotifyAlert(5)
        alert.props.title = _('Nothing to publish')
        alert.props.msg = _('Mark arcticles from "Custom" '
                            'panel and try again.')
        alert.connect('response', __alert_notify_response_cb, activity)
        activity.add_alert(alert)
        alert.show()
        return

    title = activity.metadata['title']
    jobject = datastore.find({
            'activity_id': activity.get_id(),
            'activity'   : book.custom.uid})[0] or None

    logger.debug('publish: title=%s jobject=%s force=%s' \
            % (title, jobject and jobject[0].metadata['activity'], force))

    if jobject:
        if force:
            jobject = jobject[0]
        else:
            alert = ConfirmationAlert()
            alert.props.title = _('Overwrite existed bundle?')
            alert.props.msg = _('A bundle for current object was already created. '
                                'Click "OK" to overwrite it.')
            alert.connect('response', __alert_response_cb, activity, True)
            activity.add_alert(alert)
            alert.show()
            jobject[0].destroy()
            return
    else:
        jobject = datastore.create()
        jobject.metadata['activity_id'] = activity.get_id()
        jobject.metadata['activity'] = book.custom.uid
        jobject.metadata['mime_type'] = 'application/vnd.olpc-content'
        jobject.metadata['description'] = \
                'This is a bundle containing articles on %s.\n' \
                'To view these articles, open the \'Browse\' Activity.\n' \
                'Go to \'Books\', and select \'%s\'.' % (title, title)

    book.custom.sync_article()
    book.custom.revision += 1

    jobject.metadata['title'] = title
    _publish(title, jobject)
    jobject.destroy()

    book.custom.sync_index()

    alert = NotifyAlert()
    alert.props.title = _('Book published to your Journal')
    alert.props.msg = _('You can read the book in Browse or '
                        'access the .xol file from your Journal')
    alert.connect('response', __alert_notify_response_cb, activity)
    activity.add_alert(alert)
    alert.show()
    def _save_ogg_eos_cb(self, bus, message, pipe):
        bus.remove_signal_watch()
        pipe.set_state(Gst.State.NULL)

        title = '%s saved as audio' % self.metadata['title']

        jobject = datastore.create()
        jobject.metadata['title'] = title
        jobject.metadata['keep'] = '0'
        jobject.metadata['mime_type'] = 'audio/ogg'
        jobject.file_path = self._ogg_tempfile.name
        datastore.write(jobject)

        self._wav_tempfile.close()
        self._ogg_tempfile.close()

        alert = NotifyAlert(10)
        alert.props.title = _('Audio recorded')
        alert.props.msg = _('The audio file was saved in the Journal')
        alert.connect('response', self.__alert_response_cb)
        self.add_alert(alert)

        return False
Exemple #49
0
    def _save_ogg_eos_cb(self, bus, message, pipe):
        bus.remove_signal_watch()
        pipe.set_state(Gst.State.NULL)

        title = '%s saved as audio' % self.metadata['title']

        jobject = datastore.create()
        jobject.metadata['title'] = title
        jobject.metadata['keep'] = '0'
        jobject.metadata['mime_type'] = 'audio/ogg'
        jobject.file_path = self._ogg_tempfile.name
        datastore.write(jobject)

        self._wav_tempfile.close()
        self._ogg_tempfile.close()

        alert = NotifyAlert(10)
        alert.props.title = _('Audio recorded')
        alert.props.msg = _('The audio file was saved in the Journal')
        alert.connect('response', self.__alert_response_cb)
        self.add_alert(alert)

        return False
class _SharedJournalEntry(account.SharedJournalEntry):
    __gsignals__ = {
        'transfer-state-changed': (GObject.SignalFlags.RUN_FIRST, None,
                                   ([str])),
    }

    def __init__(self, webaccount):
        self._account = webaccount
        self._alert = None

    def get_share_menu(self, get_uid_list):
        menu = _ShareMenu(self._account, get_uid_list, True)
        self._connect_transfer_signals(menu)
        logging.debug('url cache: %s' % (self._account.url_cache))
        return menu

    def get_refresh_menu(self):
        menu = _RefreshMenu(self._account, False)
        self._connect_transfer_signals(menu)
        return menu

    def _connect_transfer_signals(self, transfer_widget):
        transfer_widget.connect('transfer-state-changed',
                                self.__display_alert_cb)

    def __display_alert_cb(self, widget, message):
        if self._alert is None:
            self._alert = NotifyAlert()
            self._alert.props.title = ACCOUNT_NAME
            self._alert.connect('response', self.__alert_response_cb)
            journalwindow.get_journal_window().add_alert(self._alert)
            self._alert.show()
        self._alert.props.msg = message

    def __alert_response_cb(self, alert, response_id):
        journalwindow.get_journal_window().remove_alert(alert)
        self._alert = None
Exemple #51
0
    def check_image_qr(self, path):
        myCode = QR(filename=path)
        if myCode.decode():
            self.qr_link = myCode.data_to_string()
            self.copy_link.set_sensitive(True)
            alert = NotifyAlert(10)
            alert.props.title = _("Code found")
            alert.props.msg = _("Click on toolbar button for "
                                "copy link to clipboard.")
            alert.connect("response",
                          lambda x, y: self.activity.remove_alert(x))
            self.activity.add_alert(alert)
        else:
            self.qr_link = None
            self.copy_link.set_sensitive(False)
            alert = NotifyAlert(10)
            alert.props.title = _("Code not found")
            alert.props.msg = _("Try again, please focus the Qr "
                                "Code in the camera.")
            alert.connect("response",
                          lambda x, y: self.activity.remove_alert(x))
            self.activity.add_alert(alert)

        self.stop_play.set_sensitive(False)
Exemple #52
0
    def check_image_qr(self, path):
        myCode = QR(filename=path)
        if myCode.decode():
            self.qr_link = myCode.data_to_string()
            self.copy_link.set_sensitive(True)
            alert = NotifyAlert(10)
            alert.props.title = _("Code found")
            alert.props.msg = _("Click on toolbar button for "
                "copy link to clipboard.")
            alert.connect("response", lambda x,
                y: self.activity.remove_alert(x))
            self.activity.add_alert(alert)
        else:
            self.qr_link = None
            self.copy_link.set_sensitive(False)
            alert = NotifyAlert(10)
            alert.props.title = _("Code not found")
            alert.props.msg = _("Try again, please focus the Qr "
                "Code in the camera.")
            alert.connect("response", lambda x,
                y: self.activity.remove_alert(x))
            self.activity.add_alert(alert)

        self.stop_play.set_sensitive(False)
Exemple #53
0
class Account(account.Account):

    def __init__(self):
        self.upload = accountsmanager.get_service('sugargdrive')
        self._shared_journal_entry = None
        self._journal = None
        self._model = None
        self._alert = None
        self._listview = None
        self._volume_button = None

    def get_description(self):
        return ACCOUNT_DESCRIPTION

    def add_journal_button(self):
        if not self._journal:
            palette = ExtensionPalette()
            self._journal = get_journal()
            self._listview = self._journal.get_list_view()
            self._volumes_toolbar = self._journal.get_volumes_toolbar()

            self._volume_button = ExtensionButton(ACCOUNT_ICON, ICONS_PATH)
            self._volume_button.connect('toggled', self._journal_toggled)
            self._volume_button.connect('load-files', self._load_files)
            self._volume_button.connect('data-upload', self._upload_file)
            self._volumes_toolbar.add_extension_button(self._volume_button,
                ACCOUNT_NAME, palette)

            palette.set_item_cb(self.update_files)

    def get_token_state(self):
        return self.STATE_VALID

    def get_shared_journal_entry(self):
        if self._shared_journal_entry is None:
            self._shared_journal_entry = _SharedJournalEntry(self)

        return self._shared_journal_entry

    def _journal_toggled(self, widget):
        self._journal.get_window().set_cursor(None)
        option = widget.props.active
        if option:
            new_option = False
        else:
            new_option = True
        self._listview.use_options(new_option)

    def _load_files(self, *kwargs):
        if not self._model:
            journal_button = self._volumes_toolbar._volume_buttons[0]
            self._model = FilesModel(self.upload, self._display_alert_cb,
                self._load_files, journal_button, self._listview)
        self._model.clear()
        self._listview.tree_view.set_model(self._model)

        def internal_callback():
            files = []
            if os.path.exists(USER_FILES):
                f = open(USER_FILES, 'r')
                try:
                    data = json.load(f)
                except:
                    files = []
                    os.remove(USER_FILES)
                    self._journal.get_window().set_cursor(None)
                    f.close()
                    data = []

                isdict = False
                if isinstance(data, dict):
                    isdict = True

                if isdict:
                    data = data['items']

                for userfile in data:
                    txt = '<span weight="bold">%s</span>' % (
                        GLib.markup_escape_text(userfile['title']))
                    icon_name = _get_icon_for_mime(userfile['mimeType'])
                    link = userfile['alternateLink']

                    itter = self._model.insert(-1, [
                        '', False, icon_name,
                        profile.get_color(), txt, '', '', 50,
                        profile.get_color(), profile.get_color(),
                        profile.get_color(), True, link,
                        userfile['mimeType'],
                        userfile['id'],
                        userfile['title']])

                    files.append(itter)

            if len(files) == 0 or not os.path.exists(USER_FILES):
                self._listview._show_message(_('No files in your '
                    'account, please update your file list '
                    'clicking in the toolbar menu option.'),
                    icon_name=ACCOUNT_ICON)
            else:
                self._listview._clear_message()

            self._journal.get_window().set_cursor(None)

        self._listview._show_message(_('Loading files...'),
                icon_name=ACCOUNT_ICON)
        cursor = Gdk.Cursor.new(Gdk.CursorType.WATCH)
        self._journal.get_window().set_cursor(cursor)
        GObject.idle_add(internal_callback)

    def _upload_file(self, widget, metadata):
        account = self._shared_journal_entry._menu
        account.connect('transfer-state-changed', self._display_alert_cb)
        account.upload_file(None, metadata)

    def _display_alert_cb(self, widget, title, message):
        if self._alert is None:
            self._alert = NotifyAlert()
            self._alert.connect('response', self.__alert_response_cb)
            journalwindow.get_journal_window().add_alert(self._alert)
            self._alert.show()

        self._alert.props.title = title
        self._alert.props.msg = message

    def __alert_response_cb(self, alert, response_id):
        journalwindow.get_journal_window().remove_alert(alert)
        self._alert = None

    def update_files(self, widget):
        self._listview._show_message(_('Updating file list...'),
                icon_name=ACCOUNT_ICON)
        cursor = Gdk.Cursor.new(Gdk.CursorType.WATCH)
        self._journal.get_window().set_cursor(cursor)
        if not self._volume_button.props.active:
            self._volume_button.set_active(True)
            self._journal_toggled(self._volume_button)

        def internal_callback():
            inst = self.upload.Upload()
            inst.update_files(self._display_alert_cb, self._load_files)
            self._listview._clear_message()
            self._journal.get_window().set_cursor(None)

        GObject.idle_add(internal_callback)
Exemple #54
0
class TwitterAccount(account.Account):

    CONSUMER_TOKEN_KEY = "/desktop/sugar/collaboration/twitter_consumer_token"
    CONSUMER_SECRET_KEY = "/desktop/sugar/collaboration/twitter_consumer_secret"
    ACCESS_TOKEN_KEY = "/desktop/sugar/collaboration/twitter_access_token"
    ACCESS_SECRET_KEY = "/desktop/sugar/collaboration/twitter_access_secret"

    def __init__(self):
        self._client = GConf.Client.get_default()
        ctoken, csecret, atoken, asecret = self._access_tokens()
        TwrAccount.set_secrets(ctoken, csecret, atoken, asecret)
        self._alert = None

    def get_description(self):
        return ACCOUNT_NAME

    def is_configured(self):
        return None not in self._access_tokens()

    def is_active(self):
        # No expiration date
        return None not in self._access_tokens()

    def get_share_menu(self, journal_entry_metadata):
        twr_share_menu = _TwitterShareMenu(journal_entry_metadata,
                                          self.is_active())
        self._connect_transfer_signals(twr_share_menu)
        return twr_share_menu

    def get_refresh_menu(self):
        twr_refresh_menu = _TwitterRefreshMenu(self.is_active())
        self._connect_transfer_signals(twr_refresh_menu)
        return twr_refresh_menu

    def _connect_transfer_signals(self, transfer_widget):
        transfer_widget.connect('transfer-state-changed',
                                self._transfer_state_changed_cb)

    def _transfer_state_changed_cb(self, widget, state_message):
        logging.debug('_transfer_state_changed_cb')

        # First, remove any existing alert
        if self._alert is None:
            self._alert = NotifyAlert()
            self._alert.props.title = ACCOUNT_NAME
            self._alert.connect('response', self._alert_response_cb)
            journalwindow.get_journal_window().add_alert(self._alert)
            self._alert.show()

        logging.debug(state_message)
        self._alert.props.msg = state_message

    def _alert_response_cb(self, alert, response_id):
        journalwindow.get_journal_window().remove_alert(alert)
        self._alert = None

    def _access_tokens(self):
        return (self._client.get_string(self.CONSUMER_TOKEN_KEY),
                self._client.get_string(self.CONSUMER_SECRET_KEY),
                self._client.get_string(self.ACCESS_TOKEN_KEY),
                self._client.get_string(self.ACCESS_SECRET_KEY))
class FractionBounceActivity(activity.Activity):

    def __init__(self, handle):
        ''' Initiate activity. '''
        super(FractionBounceActivity, self).__init__(handle)

        self.nick = profile.get_nick_name()
        if profile.get_color() is not None:
            self._colors = profile.get_color().to_string().split(',')
        else:
            self._colors = ['#A0FFA0', '#FF8080']

        self.max_participants = 4  # sharing
        self._playing = True

        self._setup_toolbars()
        self._setup_dispatch_table()
        canvas = self._setup_canvas()

        # Read any custom fractions from the project metadata
        if 'custom' in self.metadata:
            custom = self.metadata['custom']
        else:
            custom = None

        self._current_ball = 'soccerball'

        self._toolbar_was_expanded = False

        # Initialize the canvas
        self._bounce_window = Bounce(canvas, activity.get_bundle_path(), self)

        Gdk.Screen.get_default().connect('size-changed', self._configure_cb)

        # Restore any custom fractions
        if custom is not None:
            fractions = custom.split(',')
            for f in fractions:
                self._bounce_window.add_fraction(f)

        if self.shared_activity:
            # We're joining
            if not self.get_shared():
                xocolors = XoColor(profile.get_color().to_string())
                share_icon = Icon(icon_name='zoom-neighborhood',
                                  xo_color=xocolors)
                self._joined_alert = NotifyAlert()
                self._joined_alert.props.icon = share_icon
                self._joined_alert.props.title = _('Please wait')
                self._joined_alert.props.msg = _('Starting connection...')
                self._joined_alert.connect('response', self._alert_cancel_cb)
                self.add_alert(self._joined_alert)

                self._label.set_label(_('Wait for the sharer to start.'))

                # Wait for joined signal
                self.connect("joined", self._joined_cb)

        self._setup_sharing()

    def _configure_cb(self, event):
        if Gdk.Screen.width() < 1024:
            self._label.set_size_request(275, -1)
            self._label.set_label('')
            self._separator.set_expand(False)
        else:
            self._label.set_size_request(500, -1)
            self._separator.set_expand(True)

        self._bounce_window.configure_cb(event)
        if self._toolbar_expanded():
            self._bounce_window.bar.bump_bars('up')
            self._bounce_window.ball.ball.move_relative(
                (0, -style.GRID_CELL_SIZE))

    def _toolbar_expanded(self):
        if self._activity_button.is_expanded():
            return True
        elif self._custom_toolbar_button.is_expanded():
            return True
        return False

    def _update_graphics(self, widget):
        # We need to catch opening and closing of toolbars and ignore
        # switching between open toolbars.
        if self._toolbar_expanded():
            if not self._toolbar_was_expanded:
                self._bounce_window.bar.bump_bars('up')
                self._bounce_window.ball.ball.move_relative(
                    (0, -style.GRID_CELL_SIZE))
                self._toolbar_was_expanded = True
        else:
            if self._toolbar_was_expanded:
                self._bounce_window.bar.bump_bars('down')
                self._bounce_window.ball.ball.move_relative(
                    (0, style.GRID_CELL_SIZE))
                self._toolbar_was_expanded = False

    def _setup_toolbars(self):
        custom_toolbar = Gtk.Toolbar()
        toolbox = ToolbarBox()
        self._toolbar = toolbox.toolbar
        self._activity_button = ActivityToolbarButton(self)
        self._activity_button.connect('clicked', self._update_graphics)
        self._toolbar.insert(self._activity_button, 0)
        self._activity_button.show()

        self._custom_toolbar_button = ToolbarButton(
            label=_('Custom'),
            page=custom_toolbar,
            icon_name='view-source')
        self._custom_toolbar_button.connect('clicked', self._update_graphics)
        custom_toolbar.show()
        self._toolbar.insert(self._custom_toolbar_button, -1)
        self._custom_toolbar_button.show()

        self._load_standard_buttons(self._toolbar)

        self._separator = Gtk.SeparatorToolItem()
        self._separator.props.draw = False
        self._separator.set_expand(True)
        self._toolbar.insert(self._separator, -1)
        self._separator.show()

        stop_button = StopButton(self)
        stop_button.props.accelerator = _('<Ctrl>Q')
        self._toolbar.insert(stop_button, -1)
        stop_button.show()
        self.set_toolbar_box(toolbox)
        toolbox.show()

        self._load_custom_buttons(custom_toolbar)

    def _load_standard_buttons(self, toolbar):
        fraction_button = RadioToolButton(group=None)
        fraction_button.set_icon_name('fraction')
        fraction_button.set_tooltip(_('fractions'))
        fraction_button.connect('clicked', self._fraction_cb)
        toolbar.insert(fraction_button, -1)
        fraction_button.show()

        sector_button = RadioToolButton(group=fraction_button)
        sector_button.set_icon_name('sector')
        sector_button.set_tooltip(_('sectors'))
        sector_button.connect('clicked', self._sector_cb)
        toolbar.insert(sector_button, -1)
        sector_button.show()

        percent_button = RadioToolButton(group=fraction_button)
        percent_button.set_icon_name('percent')
        percent_button.set_tooltip(_('percents'))
        percent_button.connect('clicked', self._percent_cb)
        toolbar.insert(percent_button, -1)
        percent_button.show()

        self._player = Gtk.Image()
        self._player.set_from_pixbuf(svg_str_to_pixbuf(
            generate_xo_svg(scale=0.8, colors=['#282828', '#282828'])))
        self._player.set_tooltip_text(self.nick)
        toolitem = Gtk.ToolItem()
        toolitem.add(self._player)
        self._player.show()
        toolbar.insert(toolitem, -1)
        toolitem.show()

        self._label = Gtk.Label(_("Click the ball to start."))
        self._label.set_line_wrap(True)
        if Gdk.Screen.width() < 1024:
            self._label.set_size_request(275, -1)
        else:
            self._label.set_size_request(500, -1)
        self.toolitem = Gtk.ToolItem()
        self.toolitem.add(self._label)
        self._label.show()
        toolbar.insert(self.toolitem, -1)
        self.toolitem.show()

    def _load_custom_buttons(self, toolbar):
        self.numerator = Gtk.Entry()
        self.numerator.set_text('')
        self.numerator.set_tooltip_text(_('numerator'))
        self.numerator.set_width_chars(3)
        toolitem = Gtk.ToolItem()
        toolitem.add(self.numerator)
        self.numerator.show()
        toolbar.insert(toolitem, -1)
        toolitem.show()

        label = Gtk.Label('   /   ')
        toolitem = Gtk.ToolItem()
        toolitem.add(label)
        label.show()
        toolbar.insert(toolitem, -1)
        toolitem.show()

        self.denominator = Gtk.Entry()
        self.denominator.set_text('')
        self.denominator.set_tooltip_text(_('denominator'))
        self.denominator.set_width_chars(3)
        toolitem = Gtk.ToolItem()
        toolitem.add(self.denominator)
        self.denominator.show()
        toolbar.insert(toolitem, -1)
        toolitem.show()

        button = ToolButton('list-add')
        button.set_tooltip(_('add new fraction'))
        button.props.sensitive = True
        button.props.accelerator = 'Return'
        button.connect('clicked', self._add_fraction_cb)
        toolbar.insert(button, -1)
        button.show()

        separator = Gtk.SeparatorToolItem()
        separator.props.draw = False
        separator.set_expand(False)
        toolbar.insert(separator, -1)
        separator.show()

        button = ToolButton('soccerball')
        button.set_tooltip(_('choose a ball'))
        button.props.sensitive = True
        button.connect('clicked', self._button_palette_cb)
        toolbar.insert(button, -1)
        button.show()
        self._ball_palette = button.get_palette()
        button_grid = Gtk.Grid()
        row = 0
        for ball in BALLDICT.keys():
            if ball == 'custom':
                button = ToolButton('view-source')
            else:
                button = ToolButton(ball)
            button.connect('clicked', self._load_ball_cb, None, ball)
            eventbox = Gtk.EventBox()
            eventbox.connect('button_press_event', self._load_ball_cb,
                             ball)
            label = Gtk.Label(BALLDICT[ball][0])
            eventbox.add(label)
            label.show()
            button_grid.attach(button, 0, row, 1, 1)
            button.show()
            button_grid.attach(eventbox, 1, row, 1, 1)
            eventbox.show()
            row += 1
        self._ball_palette.set_content(button_grid)
        button_grid.show()

        button = ToolButton('insert-picture')
        button.set_tooltip(_('choose a background'))
        button.props.sensitive = True
        button.connect('clicked', self._button_palette_cb)
        toolbar.insert(button, -1)
        button.show()
        self._bg_palette = button.get_palette()
        button_grid = Gtk.Grid()
        row = 0
        for bg in BGDICT.keys():
            if bg == 'custom':
                button = ToolButton('view-source')
            else:
                button = ToolButton(bg)
            button.connect('clicked', self._load_bg_cb, None, bg)
            eventbox = Gtk.EventBox()
            eventbox.connect('button_press_event', self._load_bg_cb, bg)
            label = Gtk.Label(BGDICT[bg][0])
            eventbox.add(label)
            label.show()
            button_grid.attach(button, 0, row, 1, 1)
            button.show()
            button_grid.attach(eventbox, 1, row, 1, 1)
            eventbox.show()
            row += 1
        self._bg_palette.set_content(button_grid)
        button_grid.show()

    def _button_palette_cb(self, button):
        palette = button.get_palette()
        if palette:
            if not palette.is_up():
                palette.popup(immediate=True, state=palette.SECONDARY)
            else:
                palette.popdown(immediate=True)

    def can_close(self):
        # Let everyone know we are leaving...
        if hasattr(self, '_bounce_window') and \
           self._bounce_window.we_are_sharing():
            self._playing = False
            self.send_event('l', {"data": (json_dump([self.nick]))})
        return True

    def _setup_canvas(self):
        canvas = Gtk.DrawingArea()
        canvas.set_size_request(Gdk.Screen.width(),
                                Gdk.Screen.height())
        self.set_canvas(canvas)
        canvas.show()
        return canvas

    def _load_bg_cb(self, widget, event, bg):
        if bg == 'custom':
            chooser(self, 'Image', self._new_background_from_journal)
        else:
            self._bounce_window.set_background(BGDICT[bg][1])

    def _load_ball_cb(self, widget, event, ball):
        if ball == 'custom':
            chooser(self, 'Image', self._new_ball_from_journal)
        else:
            self._bounce_window.ball.new_ball(os.path.join(
                activity.get_bundle_path(), 'images', ball + '.svg'))
            self._bounce_window.set_background(BGDICT[BALLDICT[ball][1]][1])
        self._current_ball = ball

    def _reset_ball(self):
        ''' If we switch back from sector mode, we need to restore the ball '''
        if self._bounce_window.mode != 'sectors':
            return

        if self._current_ball == 'custom':  # TODO: Reload custom ball
            self._current_ball = 'soccerball'
        self._bounce_window.ball.new_ball(os.path.join(
            activity.get_bundle_path(), 'images', self._current_ball + '.svg'))

    def _new_ball_from_journal(self, dsobject):
        ''' Load an image from the Journal. '''
        self._bounce_window.ball.new_ball_from_image(
            dsobject.file_path,
            os.path.join(activity.get_activity_root(), 'tmp', 'custom.png'))

    def _new_background_from_journal(self, dsobject):
        ''' Load an image from the Journal. '''
        self._bounce_window.new_background_from_image(None, dsobject=dsobject)

    def _fraction_cb(self, arg=None):
        ''' Set fraction mode '''
        self._reset_ball()
        self._bounce_window.mode = 'fractions'

    def _percent_cb(self, arg=None):
        ''' Set percent mode '''
        self._reset_ball()
        self._bounce_window.mode = 'percents'

    def _sector_cb(self, arg=None):
        ''' Set sector mode '''
        self._bounce_window.mode = 'sectors'

    def _add_fraction_cb(self, arg=None):
        ''' Read entries and add a fraction to the list '''
        try:
            numerator = int(self.numerator.get_text().strip())
        except ValueError:
            self.numerator.set_text('NAN')
            numerator = 0
        try:
            denominator = int(self.denominator.get_text().strip())
        except ValueError:
            self.denominator.set_text('NAN')
            denominator = 1
        if denominator == 0:
            self.denominator.set_text('ZDE')
        if numerator > denominator:
            numerator = 0
        if numerator > 0 and denominator > 1:
            fraction = '%d/%d' % (numerator, denominator)
            self._bounce_window.add_fraction(fraction)
            if 'custom' in self.metadata:  # Save to Journal
                self.metadata['custom'] = '%s,%s' % (
                    self.metadata['custom'], fraction)
            else:
                self.metadata['custom'] = fraction

            self.alert(
                _('New fraction'),
                _('Your fraction, %s, has been added to the program' %
                  (fraction)))

    def reset_label(self, label):
        ''' update the challenge label '''
        self._label.set_label(label)

    def alert(self, title, text=None):
        alert = NotifyAlert(timeout=5)
        alert.props.title = title
        alert.props.msg = text
        self.add_alert(alert)
        alert.connect('response', self._alert_cancel_cb)
        alert.show()

    def _alert_cancel_cb(self, alert, response_id):
        self.remove_alert(alert)

    # Collaboration-related methods

    def _setup_sharing(self):
        ''' Setup the Presence Service. '''
        self.pservice = presenceservice.get_instance()
        self.initiating = None  # sharing (True) or joining (False)

        owner = self.pservice.get_owner()
        self.owner = owner
        self._bounce_window.buddies.append(self.nick)
        self._player_colors = [self._colors]
        self._player_pixbufs = [
            svg_str_to_pixbuf(generate_xo_svg(scale=0.8, colors=self._colors))
        ]
        self._share = ''
        self.connect('shared', self._shared_cb)
        self.connect('joined', self._joined_cb)

    def _shared_cb(self, activity):
        ''' Either set up initial share...'''
        self._new_tube_common(True)

    def _joined_cb(self, activity):
        ''' ...or join an exisiting share. '''
        self._new_tube_common(False)

    def _new_tube_common(self, sharer):
        ''' Joining and sharing are mostly the same... '''
        if self.shared_activity is None:
            _logger.debug('Error: Failed to share or join activity ... \
                shared_activity is null in _shared_cb()')
            return

        self.initiating = sharer
        self.waiting_for_fraction = not sharer

        self.conn = self.shared_activity.telepathy_conn
        self.tubes_chan = self.shared_activity.telepathy_tubes_chan
        self.text_chan = self.shared_activity.telepathy_text_chan

        self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].connect_to_signal(
            'NewTube', self._new_tube_cb)

        if sharer:
            _logger.debug('This is my activity: making a tube...')
            id = self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].OfferDBusTube(
                SERVICE, {})

            self._label.set_label(_('Wait for others to join.'))
        else:
            _logger.debug('I am joining an activity: waiting for a tube...')
            self.tubes_chan[telepathy.CHANNEL_TYPE_TUBES].ListTubes(
                reply_handler=self._list_tubes_reply_cb,
                error_handler=self._list_tubes_error_cb)

        # display your XO on the toolbar
        self._player.set_from_pixbuf(self._player_pixbufs[0])

    def _list_tubes_reply_cb(self, tubes):
        ''' Reply to a list request. '''
        for tube_info in tubes:
            self._new_tube_cb(*tube_info)

    def _list_tubes_error_cb(self, e):
        ''' Log errors. '''
        _logger.debug('Error: ListTubes() failed: %s', e)

    def _new_tube_cb(self, id, initiator, type, service, params, state):
        ''' Create a new tube. '''
        _logger.debug(
            'Newtube: ID=%d initator=%d type=%d service=%s params=%r state=%d',
            id, initiator, type, service, params, state)

        if (type == telepathy.TUBE_TYPE_DBUS and service == SERVICE):
            if state == telepathy.TUBE_STATE_LOCAL_PENDING:
                self.tubes_chan[ \
                              telepathy.CHANNEL_TYPE_TUBES].AcceptDBusTube(id)

            self.collab = CollabWrapper(self)
            self.collab.message.connect(self.event_received_cb)
            self.collab.setup()

            # Let the sharer know a new joiner has arrived.
            if self.waiting_for_fraction:
                self.send_event('j', {"data": (json_dump([self.nick,
                                                     self._colors]))})

    def _setup_dispatch_table(self):
        self._processing_methods = {
            'j': [self._new_joiner, 'new joiner'],
            'b': [self._buddy_list, 'buddy list'],
            'f': [self._receive_a_fraction, 'receive a fraction'],
            't': [self._take_a_turn, 'take a turn'],
            'l': [self._buddy_left, 'buddy left']
            }

    def event_received_cb(self, event_message):
        ''' Data from a tube has arrived. '''
        if len(event_message) == 0:
            return
        try:
            command, payload = event_message.split('|', 2)
        except ValueError:
            _logger.debug('Could not split event message %s', event_message)
            return
        _logger.debug('received an event %s|%s', command, payload)
        if self._playing:
            self._processing_methods[command][0](payload)

    def _buddy_left(self, payload):
        [nick] = json_load(payload)
        self._label.set_label(nick + ' ' + _('has left.'))
        if self.initiating:
            self._remove_player(nick)
            payload = json_dump([self._bounce_window.buddies,
                                 self._player_colors])
            self.send_event('b', {"data": payload})
            # Restart from sharer's turn
            self._bounce_window.its_my_turn()

    def _new_joiner(self, payload):
        ''' Someone has joined; sharer adds them to the buddy list. '''
        [nick, colors] = json_load(payload)
        self._label.set_label(nick + ' ' + _('has joined.'))
        if self.initiating:
            self._append_player(nick, colors)
            payload = json_dump([self._bounce_window.buddies,
                                 self._player_colors])
            self.send_event('b', {"data": payload})
            if self._bounce_window.count == 0:  # Haven't started yet...
                self._bounce_window.its_my_turn()

    def _remove_player(self, nick):
        if nick in self._bounce_window.buddies:
            i = self._bounce_window.buddies.index(nick)
            self._bounce_window.buddies.remove(nick)
            self._player_colors.remove(self._player_colors[i])
            self._player_pixbufs.remove(self._player_pixbufs[i])

    def _append_player(self, nick, colors):
        ''' Keep a list of players, their colors, and an XO pixbuf '''
        if not nick in self._bounce_window.buddies:
            _logger.debug('appending %s to the buddy list', nick)
            self._bounce_window.buddies.append(nick)
            self._player_colors.append([str(colors[0]), str(colors[1])])
            self._player_pixbufs.append(svg_str_to_pixbuf(
                generate_xo_svg(scale=0.8,
                                colors=self._player_colors[-1])))

    def _buddy_list(self, payload):
        '''Sharer sent the updated buddy list, so regenerate internal lists'''
        if not self.initiating:
            [buddies, colors] = json_load(payload)
            self._bounce_window.buddies = buddies[:]
            self._player_colors = colors[:]
            self._player_pixbufs = []
            for colors in self._player_colors:
                self._player_pixbufs.append(svg_str_to_pixbuf(
                    generate_xo_svg(scale=0.8,
                                    colors=[str(colors[0]), str(colors[1])])))

    def send_a_fraction(self, fraction):
        ''' Send a fraction to other players. '''
        payload = json_dump(fraction)
        self.send_event('f', {"data": payload})

    def _receive_a_fraction(self, payload):
        ''' Receive a fraction from another player. '''
        fraction = json_load(payload)
        self._bounce_window.play_a_fraction(fraction)

    def _take_a_turn(self, nick):
        ''' If it is your turn, take it, otherwise, wait. '''
        if nick == self.nick:
            self._bounce_window.its_my_turn()
        else:
            self._bounce_window.its_their_turn(nick)

    def send_event(self, command, data):
        ''' Send event through the tube. '''
        _logger.debug('sending event: %s', command)
        if hasattr(self, 'collab') and self.collab is not None:
            data["command"] = command
            self.collab.post(data)

    def set_player_on_toolbar(self, nick):
        ''' Display the XO icon of the player whose turn it is. '''
        self._player.set_from_pixbuf(self._player_pixbufs[
                self._bounce_window.buddies.index(nick)])
        self._player.set_tooltip_text(nick)
Exemple #56
0
class MazeActivity(activity.Activity):

    def __init__(self, handle):
        """Set up the Maze activity."""
        activity.Activity.__init__(self, handle)
        self._busy_count = 0
        self._unbusy_idle_sid = None

        self.build_toolbar()

        self.pservice = PresenceService()
        self.owner = self.pservice.get_owner()

        state = None
        if 'state' in self.metadata:
            state = json.loads(self.metadata['state'])
        self.game = game.MazeGame(self, self.owner, state)
        self.set_canvas(self.game)
        self.game.show()
        self.connect("key_press_event", self.game.key_press_cb)

        self.text_channel = None
        self.my_key = profile.get_pubkey()
        self._alert = None

        if self.shared_activity:
            # we are joining the activity
            self._add_alert(_('Joining a maze'), _('Connecting...'))
            self.connect('joined', self._joined_cb)
            if self.get_shared():
                # we have already joined
                self._joined_cb()
        else:
            # we are creating the activity
            self.connect('shared', self._shared_cb)

    def busy(self):
        if self._busy_count == 0:
            if self._unbusy_idle_sid is not None:
                GLib.source_remove(self._unbusy_idle_sid)
                self._unbusy_idle_sid = None
            self._old_cursor = self.get_window().get_cursor()
            self._set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH))
        self._busy_count += 1

    def unbusy(self):
        self._unbusy_idle_sid = GLib.idle_add(self._unbusy_idle_cb)

    def _unbusy_idle_cb(self):
        self._unbusy_idle_sid = None
        self._busy_count -= 1
        if self._busy_count == 0:
            self._set_cursor(self._old_cursor)

    def _set_cursor(self, cursor):
        self.get_window().set_cursor(cursor)
        Gdk.flush()

    def build_toolbar(self):
        """Build our Activity toolbar for the Sugar system."""

        toolbar_box = ToolbarBox()
        activity_button = ActivityToolbarButton(self)
        toolbar_box.toolbar.insert(activity_button, 0)
        activity_button.show()

        separator = Gtk.SeparatorToolItem()
        toolbar_box.toolbar.insert(separator, -1)
        separator.show()

        easier_button = ToolButton('create-easier')
        easier_button.set_tooltip(_('Easier level'))
        easier_button.connect('clicked', self._easier_button_cb)
        toolbar_box.toolbar.insert(easier_button, -1)

        harder_button = ToolButton('create-harder')
        harder_button.set_tooltip(_('Harder level'))
        harder_button.connect('clicked', self._harder_button_cb)
        toolbar_box.toolbar.insert(harder_button, -1)

        separator = Gtk.SeparatorToolItem()
        toolbar_box.toolbar.insert(separator, -1)
        separator.show()

        self.show_trail_button = ToggleToolButton('show-trail')
        self.show_trail_button.set_tooltip(_('Show trail'))
        self.show_trail_button.set_active(True)
        self.show_trail_button.connect('toggled', self._toggled_show_trail_cb)
        toolbar_box.toolbar.insert(self.show_trail_button, -1)

        separator = Gtk.SeparatorToolItem()
        separator.props.draw = False
        separator.set_size_request(0, -1)
        separator.set_expand(True)
        toolbar_box.toolbar.insert(separator, -1)
        separator.show()

        stop_button = StopButton(self)
        toolbar_box.toolbar.insert(stop_button, -1)
        stop_button.show()

        self.set_toolbar_box(toolbar_box)
        toolbar_box.show_all()

        return toolbar_box

    def _easier_button_cb(self, button):
        self.game.easier()

    def _harder_button_cb(self, button):
        self.game.harder()

    def _toggled_show_trail_cb(self, button):
        if self.game.set_show_trail(button.get_active()):
            self.broadcast_msg('show_trail:%s' % str(button.get_active()))

    def _shared_cb(self, activity):
        logging.debug('Maze was shared')
        self._add_alert(_('Sharing'), _('This maze is shared.'))
        self._setup()

    def _joined_cb(self, activity):
        """Joined a shared activity."""
        if not self.shared_activity:
            return
        logging.debug('Joined a shared chat')
        for buddy in self.shared_activity.get_joined_buddies():
            self._buddy_already_exists(buddy)
        self._setup()
        # request maze data
        self.broadcast_msg('req_maze')

    def _setup(self):
        self.text_channel = TextChannelWrapper(
            self.shared_activity.telepathy_text_chan,
            self.shared_activity.telepathy_conn, self.pservice)
        self.text_channel.set_received_callback(self._received_cb)
        self.shared_activity.connect('buddy-joined', self._buddy_joined_cb)
        self.shared_activity.connect('buddy-left', self._buddy_left_cb)

    def _received_cb(self, buddy, text):
        if buddy == self.owner:
            return
        self.game.msg_received(buddy, text)

    def _add_alert(self, title, text=None):
        self.grab_focus()
        self._alert = ErrorAlert()
        self._alert.props.title = title
        self._alert.props.msg = text
        self.add_alert(self._alert)
        self._alert.connect('response', self._alert_cancel_cb)
        self._alert.show()

    def _alert_cancel_cb(self, alert, response_id):
        self.remove_alert(alert)
        self._alert = None

    def update_alert(self, title, text=None):
        if self._alert is not None:
            self._alert.props.title = title
            self._alert.props.msg = text

    def show_accelerator_alert(self):
        self.grab_focus()
        self._alert = NotifyAlert()
        self._alert.props.title = _('Tablet mode detected.')
        self._alert.props.msg = _('Hold your XO flat and tilt to play!')
        self.add_alert(self._alert)
        self._alert.connect('response', self._alert_cancel_cb)
        self._alert.show()

    def _buddy_joined_cb(self, activity, buddy):
        """Show a buddy who joined"""
        logging.debug('buddy joined')
        if buddy == self.owner:
            logging.debug('its me, exit!')
            return
        self.game.buddy_joined(buddy)

    def _buddy_left_cb(self, activity, buddy):
        self.game.buddy_left(buddy)

    def _buddy_already_exists(self, buddy):
        """Show a buddy already in the chat."""
        if buddy == self.owner:
            return
        self.game.buddy_joined(buddy)

    def broadcast_msg(self, message):
        if self.text_channel:
            # FIXME: can't identify the sender at the other end,
            # add the pubkey to the text message
            self.text_channel.send('%s|%s' % (self.my_key, message))

    def write_file(self, file_path):
        logging.debug('Saving the state of the game...')
        data = {'seed': self.game.maze.seed,
                'width': self.game.maze.width,
                'height': self.game.maze.height,
                'finish_time': self.game.finish_time}
        logging.debug('Saving data: %s', data)
        self.metadata['state'] = json.dumps(data)

    def can_close(self):
        self.game.close_finish_window()
        return True

    def read_file(self, file_path):
        pass
    def _create_custom_food_cb(self, button):

        def _notification_alert_response_cb(alert, response_id, self):
            self.remove_alert(alert)

        name = self.name_entry.get_text()
        try:
            calories = int(self.calories_entry.get_text())
        except:
            _logger.debug(self.calories_entry.get_text)
            calories = None
        pyramid = self.food_spinner.get_active()

        if name == '' or name == _('food name'):
            alert = NotifyAlert()
            alert.props.title = _('Add a new food item.')
            alert.connect('response', _notification_alert_response_cb, self)
            alert.props.msg = _('You must enter a name for the new food item.')
            self.add_alert(alert)
            alert.show()
            return
        elif calories is None or calories < 0:
            alert = NotifyAlert()
            alert.props.title = _('Add a new food item.')
            alert.connect('response', _notification_alert_response_cb, self)
            alert.props.msg = _('You must enter calories for the new food \
item.')
            self.add_alert(alert)
            alert.show()
            return
        elif self._custom_food_jobject is None:
            alert = NotifyAlert()
            alert.props.title = _('Add a new food item.')
            alert.connect('response', _notification_alert_response_cb, self)
            alert.props.msg = _('You must load an image for the new food \
item.')
            self.add_alert(alert)
            alert.show()
            return

        _logger.debug(self._custom_food_jobject.file_path)
        FOOD.append([name, calories, pyramid, 'apple.png'])
        self._game.word_card_append(self._game.food_cards,
                                    self._game.pixbuf)
        self._game.food_cards[-1].type = len(FOOD) - 1
        self._game.food_cards[-1].set_label(name)
        self._game.picture_append(self._custom_food_jobject.file_path)
        self._game.small_picture_append(self._custom_food_jobject.file_path)
        alert = NotifyAlert()
        alert.props.title = _('Add a new food item.')
        alert.connect('response', _notification_alert_response_cb, self)
        alert.props.msg = _('%s has been loaded.') % (name)
        self.add_alert(alert)
        alert.show()
        self.name_entry.set_text(_('food name'))
        self.calories_entry.set_text(_('calories'))
        self._custom_food_image_path = None
        self._game.build_food_groups()
        self._game.new_game()
        self.metadata['name-%d' % (self._custom_food_counter)] = name
        self.metadata['calories-%d' % (self._custom_food_counter)] = \
            str(calories)
        self.metadata['pyramid-%d' % (self._custom_food_counter)] = str(pyramid)
        self.metadata['jobject-%d' % (self._custom_food_counter)] = \
            self._custom_food_jobject.object_id
        self._custom_food_counter += 1
        _logger.debug('writing %d to counter' % (self._custom_food_counter))
        self.metadata['counter'] = str(self._custom_food_counter)
        return