Ejemplo n.º 1
0
    def __init__(self, handle):
        """ 
	    __init__ function initializes the variables needed
        """
        self.chatbox = ChatBox()
        super(ChatStudioSelf, self).__init__(handle)
        self.entry = None
        root = self.make_root()
        self.set_canvas(root)
        root.show_all()
        self.entry.grab_focus()
	self.local_first_num = 0
	self.local_second_num = 0
	self.limit_num = 50
	self.calculated_sum = 0
	self.calculated_diff = 0
	self.second_attempt_flag = False
	self.metadata_dict = {}
	self.mode_of_game = ""
	self.game_metadata = False
	self.difficulty_level = "Easy"
	self.first_come_check = 0
	self.create_toolbar()
        self.entry.set_sensitive(False)
        pservice = presenceservice.get_instance()
        self.owner = pservice.get_owner()
        # Chat is room or one to one:
        self._chat_is_room = False
Ejemplo n.º 2
0
    def make_root(self):
        entry = gtk.Entry()
        entry.modify_bg(gtk.STATE_INSENSITIVE,
                        style.COLOR_WHITE.get_gdk_color())
        entry.modify_base(gtk.STATE_INSENSITIVE,
                          style.COLOR_WHITE.get_gdk_color())
        entry.set_sensitive(False)
        entry.connect('activate', self.entry_activate_cb)
        self.entry = entry

        self.chatbox = ChatBox()

        hbox = gtk.HBox()
        hbox.add(entry)

        box = gtk.VBox(homogeneous=False)
        box.pack_start(self.chatbox)
        box.pack_start(hbox, expand=False)

        return box
Ejemplo n.º 3
0
    def __init__(self, handle):
        pservice = presenceservice.get_instance()
        self.owner = pservice.get_owner()

        self._ebook_mode_detector = EbookModeDetector()

        self.chatbox = ChatBox(self.owner,
                               self._ebook_mode_detector.get_ebook_mode())
        self.chatbox.connect('open-on-journal', self.__open_on_journal)
        self.chatbox.connect('new-message',
                             self._search_entry_on_new_message_cb)

        super(Chat, self).__init__(handle)

        self._entry = None
        self._has_alert = False
        self._has_osk = False

        self._setup_canvas()

        self._entry.grab_focus()

        toolbar_box = ToolbarBox()
        self.set_toolbar_box(toolbar_box)

        self._activity_toolbar_button = ActivityToolbarButton(self)
        self._activity_toolbar_button.connect('clicked', self._fixed_resize_cb)

        toolbar_box.toolbar.insert(self._activity_toolbar_button, 0)
        self._activity_toolbar_button.show()

        self.search_entry = iconentry.IconEntry()
        self.search_entry.set_size_request(Gdk.Screen.width() / 3, -1)
        self.search_entry.set_icon_from_name(iconentry.ICON_ENTRY_PRIMARY,
                                             'entry-search')
        self.search_entry.add_clear_button()
        self.search_entry.connect('activate', self._search_entry_activate_cb)
        self.search_entry.connect('changed', self._search_entry_activate_cb)

        self.connect('key-press-event', self._search_entry_key_press_cb)

        self._search_item = Gtk.ToolItem()
        self._search_item.add(self.search_entry)
        toolbar_box.toolbar.insert(self._search_item, -1)

        self._search_prev = ToolButton('go-previous-paired')
        self._search_prev.set_tooltip(_('Previous'))
        self._search_prev.props.accelerator = "<Shift><Ctrl>g"
        self._search_prev.connect('clicked', self._search_prev_cb)
        self._search_prev.props.sensitive = False
        toolbar_box.toolbar.insert(self._search_prev, -1)

        self._search_next = ToolButton('go-next-paired')
        self._search_next.set_tooltip(_('Next'))
        self._search_next.props.accelerator = "<Ctrl>g"
        self._search_next.connect('clicked', self._search_next_cb)
        self._search_next.props.sensitive = False
        toolbar_box.toolbar.insert(self._search_next, -1)

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

        toolbar_box.toolbar.insert(StopButton(self), -1)
        toolbar_box.show_all()

        # Chat is room or one to one:
        self._chat_is_room = False
        self.text_channel = None

        if _HAS_SOUND:
            self.element = Gst.ElementFactory.make('playbin', 'Player')

        if self.shared_activity:
            # we are joining the activity following an invite
            self._alert(_('Off-line'), _('Joining the Chat.'))
            self._entry.props.placeholder_text = \
                _('Please wait for a connection before starting to chat.')
            self.connect('joined', self._joined_cb)
            if self.get_shared():
                # we have already joined
                self._joined_cb(self)
        elif handle.uri:
            # XMPP non-sugar3 incoming chat, not sharable
            self._activity_toolbar_button.props.page.share.props.visible = \
                False
            self._one_to_one_connection(handle.uri)
        else:
            # we are creating the activity
            if not self.metadata or self.metadata.get(
                    'share-scope', activity.SCOPE_PRIVATE) == \
                    activity.SCOPE_PRIVATE:
                # if we are in private session
                self._alert(_('Off-line'), _('Share, or invite someone.'))
            else:
                # resume of shared activity from journal object without invite
                self._entry.props.placeholder_text = \
                    _('Please wait for a connection before starting to chat.')
            self.connect('shared', self._shared_cb)
Ejemplo n.º 4
0
class Chat(activity.Activity):
    def __init__(self, handle):
        pservice = presenceservice.get_instance()
        self.owner = pservice.get_owner()

        self._ebook_mode_detector = EbookModeDetector()

        self.chatbox = ChatBox(self.owner,
                               self._ebook_mode_detector.get_ebook_mode())
        self.chatbox.connect('open-on-journal', self.__open_on_journal)
        self.chatbox.connect('new-message',
                             self._search_entry_on_new_message_cb)

        super(Chat, self).__init__(handle)

        self._entry = None
        self._has_alert = False
        self._has_osk = False

        self._setup_canvas()

        self._entry.grab_focus()

        toolbar_box = ToolbarBox()
        self.set_toolbar_box(toolbar_box)

        self._activity_toolbar_button = ActivityToolbarButton(self)
        self._activity_toolbar_button.connect('clicked', self._fixed_resize_cb)

        toolbar_box.toolbar.insert(self._activity_toolbar_button, 0)
        self._activity_toolbar_button.show()

        self.search_entry = iconentry.IconEntry()
        self.search_entry.set_size_request(Gdk.Screen.width() / 3, -1)
        self.search_entry.set_icon_from_name(iconentry.ICON_ENTRY_PRIMARY,
                                             'entry-search')
        self.search_entry.add_clear_button()
        self.search_entry.connect('activate', self._search_entry_activate_cb)
        self.search_entry.connect('changed', self._search_entry_activate_cb)

        self.connect('key-press-event', self._search_entry_key_press_cb)

        self._search_item = Gtk.ToolItem()
        self._search_item.add(self.search_entry)
        toolbar_box.toolbar.insert(self._search_item, -1)

        self._search_prev = ToolButton('go-previous-paired')
        self._search_prev.set_tooltip(_('Previous'))
        self._search_prev.props.accelerator = "<Shift><Ctrl>g"
        self._search_prev.connect('clicked', self._search_prev_cb)
        self._search_prev.props.sensitive = False
        toolbar_box.toolbar.insert(self._search_prev, -1)

        self._search_next = ToolButton('go-next-paired')
        self._search_next.set_tooltip(_('Next'))
        self._search_next.props.accelerator = "<Ctrl>g"
        self._search_next.connect('clicked', self._search_next_cb)
        self._search_next.props.sensitive = False
        toolbar_box.toolbar.insert(self._search_next, -1)

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

        toolbar_box.toolbar.insert(StopButton(self), -1)
        toolbar_box.show_all()

        # Chat is room or one to one:
        self._chat_is_room = False
        self.text_channel = None

        if _HAS_SOUND:
            self.element = Gst.ElementFactory.make('playbin', 'Player')

        if self.shared_activity:
            # we are joining the activity following an invite
            self._alert(_('Off-line'), _('Joining the Chat.'))
            self._entry.props.placeholder_text = \
                _('Please wait for a connection before starting to chat.')
            self.connect('joined', self._joined_cb)
            if self.get_shared():
                # we have already joined
                self._joined_cb(self)
        elif handle.uri:
            # XMPP non-sugar3 incoming chat, not sharable
            self._activity_toolbar_button.props.page.share.props.visible = \
                False
            self._one_to_one_connection(handle.uri)
        else:
            # we are creating the activity
            if not self.metadata or self.metadata.get(
                    'share-scope', activity.SCOPE_PRIVATE) == \
                    activity.SCOPE_PRIVATE:
                # if we are in private session
                self._alert(_('Off-line'), _('Share, or invite someone.'))
            else:
                # resume of shared activity from journal object without invite
                self._entry.props.placeholder_text = \
                    _('Please wait for a connection before starting to chat.')
            self.connect('shared', self._shared_cb)

    def _search_entry_key_press_cb(self, activity, event):
        keyname = Gdk.keyval_name(event.keyval).lower()
        if keyname == 'f':
            if Gdk.ModifierType.CONTROL_MASK & event.state:
                self.search_entry.grab_focus()
        elif keyname == 'escape':
            self.search_entry.props.text = ''
            self._entry.grab_focus()

    def _search_entry_on_new_message_cb(self, chatbox):
        self._search_entry_activate_cb(self.search_entry)

    def _search_entry_activate_cb(self, entry):
        for i in range(0, self.chatbox.number_of_textboxes()):
            textbox = self.chatbox.get_textbox(i)
            _buffer = textbox.get_buffer()
            start_mark = _buffer.get_mark('start')
            end_mark = _buffer.get_mark('end')
            if start_mark is None or end_mark is None:
                continue
            _buffer.delete_mark(start_mark)
            _buffer.delete_mark(end_mark)
            self.chatbox.highlight_text = (None, None, None)
        self.chatbox.set_search_text(entry.props.text)
        self._update_search_buttons()

    def _update_search_buttons(self, ):
        if len(self.chatbox.search_text) == 0:
            self._search_prev.props.sensitive = False
            self._search_next.props.sensitive = False
        else:
            # If next or previous result exists
            self._search_prev.props.sensitive = \
                self.chatbox.check_next('backward')
            self._search_next.props.sensitive = \
                self.chatbox.check_next('forward')

    def _search_prev_cb(self, button):
        if button.props.sensitive:
            self.chatbox.search('backward')
            self._update_search_buttons()

    def _search_next_cb(self, button):
        if button.props.sensitive:
            self.chatbox.search('forward')
            self._update_search_buttons()

    def _fixed_resize_cb(self, widget=None, rect=None):
        ''' If a toolbar opens or closes, we need to resize the vbox
        holding out scrolling window. '''
        if self._has_alert:
            dy = style.GRID_CELL_SIZE
        else:
            dy = 0
        if self._has_osk:
            if Gdk.Screen.width() > Gdk.Screen.height():
                dy += OSK_HEIGHT[0]
            else:
                dy += OSK_HEIGHT[1]

        if self._toolbar_expanded():
            self.chatbox.set_size_request(
                self._chat_width,
                self._chat_height - style.GRID_CELL_SIZE - dy)
            self._fixed.move(self._entry_grid, style.GRID_CELL_SIZE,
                             self._chat_height - style.GRID_CELL_SIZE - dy)
        else:
            self.chatbox.set_size_request(self._chat_width,
                                          self._chat_height - dy)
            self._fixed.move(self._entry_grid, style.GRID_CELL_SIZE,
                             self._chat_height - dy)

        self.chatbox.resize_conversation(dy)

    def _setup_canvas(self):
        ''' Create a canvas '''
        self._fixed = Gtk.Fixed()
        self._fixed.set_size_request(
            Gdk.Screen.width(),
            Gdk.Screen.height() - style.GRID_CELL_SIZE)
        self._fixed.connect('size-allocate', self._fixed_resize_cb)
        self.set_canvas(self._fixed)
        self._fixed.show()

        self._entry_widgets = self._make_entry_widgets()
        self._fixed.put(self.chatbox, 0, 0)
        self.chatbox.show()

        self._fixed.put(self._entry_grid, style.GRID_CELL_SIZE,
                        self._chat_height)
        self._entry_grid.show()

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

    def _configure_cb(self, event):
        self._fixed.set_size_request(
            Gdk.Screen.width(),
            Gdk.Screen.height() - style.GRID_CELL_SIZE)
        if self._ebook_mode_detector.get_ebook_mode():
            self._entry_height = int(style.GRID_CELL_SIZE * 1.5)
        else:
            self._entry_height = style.GRID_CELL_SIZE
        entry_width = Gdk.Screen.width() - \
            2 * (self._entry_height + style.GRID_CELL_SIZE)
        self._entry.set_size_request(entry_width, self._entry_height)
        self._entry_grid.set_size_request(
            Gdk.Screen.width() - 2 * style.GRID_CELL_SIZE, self._entry_height)

        self._chat_height = Gdk.Screen.height() - self._entry_height - \
            style.GRID_CELL_SIZE
        self._chat_width = Gdk.Screen.width()
        self.chatbox.set_size_request(self._chat_width, self._chat_height)
        self.chatbox.resize_all()

        width = int(Gdk.Screen.width() - 2 * style.GRID_CELL_SIZE)
        if self._ebook_mode_detector.get_ebook_mode():
            height = int(Gdk.Screen.height() - 8 * style.GRID_CELL_SIZE)
        else:
            height = int(Gdk.Screen.height() - 5 * style.GRID_CELL_SIZE)
        self._smiley_table.set_size_request(width, height)
        self._smiley_toolbar.set_size_request(width, -1)
        self._smiley_window.set_size_request(width, -1)

        self._fixed_resize_cb()

    def _create_smiley_table(self, width):
        pixel_size = (style.STANDARD_ICON_SIZE + style.LARGE_ICON_SIZE) / 2
        spacing = style.DEFAULT_SPACING
        button_size = pixel_size + spacing
        smilies_columns = int(width / button_size)
        pad = (width - smilies_columns * button_size) / 2

        table = Gtk.Grid()
        table.set_row_spacing(spacing)
        table.set_column_spacing(spacing)
        table.set_border_width(pad)

        queue = []

        def _create_smiley_icon_idle_cb():
            try:
                x, y, path, code = queue.pop()
            except IndexError:
                self.unbusy()
                return False
            pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(
                path, pixel_size, pixel_size)
            image = Gtk.Image.new_from_pixbuf(pixbuf)
            box = Gtk.EventBox()
            box.add(image)
            box.connect('button-press-event', self._add_smiley_to_entry, code)
            table.attach(box, x, y, 1, 1)
            box.show_all()
            return True

        x = 0
        y = 0
        smilies.init()
        for i in range(len(smilies.THEME)):
            path, hint, codes = smilies.THEME[i]
            queue.append([x, y, path, codes[0]])

            x += 1
            if x == smilies_columns:
                y += 1
                x = 0

        queue.reverse()
        GLib.idle_add(_create_smiley_icon_idle_cb)
        return table

    def _add_smiley_to_entry(self, icon, event, text):
        pos = self._entry.props.cursor_position
        self._entry.insert_text(text, pos)
        self._entry.grab_focus()
        self._entry.set_position(pos + len(text))
        self._hide_smiley_window()

    def _shared_cb(self, sender):
        self._setup()

    def _one_to_one_connection(self, tp_channel):
        '''Handle a private invite from a non-sugar3 XMPP client.'''
        if self.shared_activity or self.text_channel:
            return
        bus_name, connection, channel = json.loads(tp_channel)
        logger.debug('GOT XMPP: %s %s %s', bus_name, connection, channel)
        conn = {}
        conn_proxy = dbus.Bus().get_object(bus_name, connection)
        conn[TelepathyGLib.IFACE_CONNECTION_INTERFACE_ALIASING] = \
            dbus.Interface(
                conn_proxy, TelepathyGLib.IFACE_CONNECTION_INTERFACE_ALIASING)
        self._one_to_one_connection_ready_cb(bus_name, channel, conn)

    def _one_to_one_connection_ready_cb(self, bus_name, channel, conn):
        '''Callback for Connection for one to one connection'''
        text_channel = {}
        text_proxy = dbus.Bus().get_object(bus_name, channel)
        text_channel[TelepathyGLib.IFACE_CHANNEL] = \
            dbus.Interface(text_proxy, TelepathyGLib.IFACE_CHANNEL)
        text_channel[TelepathyGLib.IFACE_CHANNEL_TYPE_TEXT] = \
            dbus.Interface(text_proxy, TelepathyGLib.IFACE_CHANNEL_TYPE_TEXT)
        text_channel[TelepathyGLib.IFACE_CHANNEL_INTERFACE_GROUP] = \
            dbus.Interface(
                text_proxy, TelepathyGLib.IFACE_CHANNEL_INTERFACE_GROUP)
        self.text_channel = TextChannelWrapper(text_channel, conn)
        self.text_channel.set_received_callback(self._received_cb)
        self.text_channel.handle_pending_messages()
        self.text_channel.set_closed_callback(
            self._one_to_one_connection_closed_cb)
        self._chat_is_room = False
        self._alert(_('On-line'), _('Private chat.'))

        # XXX How do we detect the sender going offline?
        self._entry.set_sensitive(True)
        self._entry.props.placeholder_text = None
        self._entry.grab_focus()

    def _one_to_one_connection_closed_cb(self):
        '''Callback for when the text channel closes.'''
        self._alert(_('Off-line'), _('Left the chat.'))

    def _setup(self):
        self.text_channel = TextChannelWrapper(
            self.shared_activity.telepathy_text_chan,
            self.shared_activity.telepathy_conn)
        self.text_channel.set_received_callback(self._received_cb)
        self._alert(_('On-line'), _('Connected.'))
        self.shared_activity.connect('buddy-joined', self._buddy_joined_cb)
        self.shared_activity.connect('buddy-left', self._buddy_left_cb)
        self._chat_is_room = True
        self._entry.set_sensitive(True)
        self._entry.props.placeholder_text = None
        self._entry.grab_focus()

    def _joined_cb(self, sender):
        '''Joined a shared activity.'''
        if not self.shared_activity:
            return
        logger.debug('Joined a shared chat')
        for buddy in self.shared_activity.get_joined_buddies():
            self._buddy_already_exists(buddy)
        self._setup()

    def _received_cb(self, buddy, text):
        '''Show message that was received.'''
        if buddy:
            if type(buddy) is dict:
                nick = buddy['nick']
            else:
                nick = buddy.props.nick
        else:
            nick = '???'
        logger.debug('Received message from %s: %s', nick, text)
        self.chatbox.add_text(buddy, text)

        if self.owner.props.nick in text:
            self.play_sound('said_nick')
        '''
        vscroll = self.chatbox.get_vadjustment()
        if vscroll.get_property('value') != vscroll.get_property('upper'):
            self._alert(_('New message'), _('New message from %s' % nick))
        '''
        if not self.has_focus:
            self.notify_user(_('Message from %s') % buddy, text)

    def _toolbar_expanded(self):
        if self._activity_toolbar_button.is_expanded():
            return True
        return False

    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_cancel_cb(self, alert, response_id):
        self.remove_alert(alert)
        self._has_alert = False
        self._fixed_resize_cb()

    def __open_on_journal(self, widget, url):
        '''Ask the journal to display a URL'''
        logger.debug('Create journal entry for URL: %s', url)
        jobject = datastore.create()
        metadata = {
            'title': '%s: %s' % (_('URL from Chat'), url),
            'title_set_by_user': '******',
            'icon-color': profile.get_color().to_string(),
            'mime_type': 'text/uri-list',
        }
        for k, v in list(metadata.items()):
            jobject.metadata[k] = v
        file_path = os.path.join(get_activity_root(), 'instance',
                                 '%i_' % time.time())
        open(file_path, 'w').write(url + '\r\n')
        os.chmod(file_path, 0o755)
        jobject.set_file_path(file_path)
        datastore.write(jobject)
        show_object_in_journal(jobject.object_id)
        jobject.destroy()
        os.unlink(file_path)

    def _buddy_joined_cb(self, sender, buddy):
        '''Show a buddy who joined'''
        if buddy == self.owner:
            return
        self.chatbox.add_text(buddy,
                              _('%s joined the chat') % buddy.props.nick,
                              status_message=True)

        self.play_sound('login')

    def _buddy_left_cb(self, sender, buddy):
        '''Show a buddy who joined'''
        if buddy == self.owner:
            return
        self.chatbox.add_text(buddy,
                              _('%s left the chat') % buddy.props.nick,
                              status_message=True)

        self.play_sound('logout')

    def _buddy_already_exists(self, buddy):
        '''Show a buddy already in the chat.'''
        if buddy == self.owner:
            return
        self.chatbox.add_text(buddy,
                              _('%s is here') % buddy.props.nick,
                              status_message=True)

    def can_close(self):
        '''Perform cleanup before closing.
        Close text channel of a one to one XMPP chat.
        '''
        if self._chat_is_room is False:
            if self.text_channel is not None:
                self.text_channel.close()
        return True

    def _make_entry_widgets(self):
        '''We need to create a button for the smiley, a text entry, and a
        send button.

        All of this, along with the chatbox, goes into a grid.

        ---------------------------------------
        | chat box                            |
        | smiley button | entry | send button |
        ---------------------------------------
        '''
        if self._ebook_mode_detector.get_ebook_mode():
            self._entry_height = int(style.GRID_CELL_SIZE * 1.5)
        else:
            self._entry_height = style.GRID_CELL_SIZE
        entry_width = Gdk.Screen.width() - \
            2 * (self._entry_height + style.GRID_CELL_SIZE)
        self._chat_height = Gdk.Screen.height() - self._entry_height - \
            style.GRID_CELL_SIZE
        self._chat_width = Gdk.Screen.width()

        self.chatbox.set_size_request(self._chat_width, self._chat_height)

        self._entry_grid = Gtk.Grid()
        self._entry_grid.set_size_request(
            Gdk.Screen.width() - 2 * style.GRID_CELL_SIZE, self._entry_height)

        smiley_button = EventIcon(icon_name='smilies',
                                  pixel_size=self._entry_height)
        smiley_button.connect('button-press-event', self._smiley_button_cb)
        self._entry_grid.attach(smiley_button, 0, 0, 1, 1)
        smiley_button.show()

        self._entry = Gtk.Entry()
        self._entry.set_size_request(entry_width, self._entry_height)
        self._entry.modify_bg(Gtk.StateType.INSENSITIVE,
                              style.COLOR_WHITE.get_gdk_color())
        self._entry.modify_base(Gtk.StateType.INSENSITIVE,
                                style.COLOR_WHITE.get_gdk_color())

        self._entry.set_sensitive(False)
        self._entry.props.placeholder_text = \
            _('You must be connected to a friend before starting to chat.')
        self._entry.connect('focus-in-event', self._entry_focus_in_cb)
        self._entry.connect('focus-out-event', self._entry_focus_out_cb)
        self._entry.connect('activate', self._entry_activate_cb)
        self._entry.connect('key-press-event', self._entry_key_press_cb)
        self._entry_grid.attach(self._entry, 1, 0, 1, 1)
        self._entry.show()

        send_button = EventIcon(icon_name='send',
                                pixel_size=self._entry_height)
        send_button.connect('button-press-event', self._send_button_cb)
        self._entry_grid.attach(send_button, 2, 0, 1, 1)
        send_button.show()

    def _get_icon_pixbuf(self, name):
        icon_theme = Gtk.IconTheme.get_default()
        icon_info = icon_theme.lookup_icon(name, style.LARGE_ICON_SIZE, 0)
        pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(
            icon_info.get_filename(), style.LARGE_ICON_SIZE,
            style.LARGE_ICON_SIZE)
        del icon_info
        return pixbuf

    def _entry_focus_in_cb(self, entry, event):
        self._hide_smiley_window()

        if self._ebook_mode_detector.get_ebook_mode():
            self._has_osk = True
            self._fixed_resize_cb()

    def _entry_focus_out_cb(self, entry, event):
        if self._ebook_mode_detector.get_ebook_mode():
            self._has_osk = False
            self._fixed_resize_cb()

    def _entry_key_press_cb(self, widget, event):
        '''Check for scrolling keys.

        Check if the user pressed Page Up, Page Down, Home or End and
        scroll the window according the pressed key.
        '''
        vadj = self.chatbox.get_vadjustment()
        if event.keyval == Gdk.KEY_Page_Down:
            value = vadj.get_value() + vadj.page_size
            if value > vadj.upper - vadj.page_size:
                value = vadj.upper - vadj.page_size
            vadj.set_value(value)
        elif event.keyval == Gdk.KEY_Page_Up:
            vadj.set_value(vadj.get_value() - vadj.page_size)
        elif event.keyval == Gdk.KEY_Home and \
                event.get_state() & Gdk.ModifierType.CONTROL_MASK:
            vadj.set_value(vadj.lower)
        elif event.keyval == Gdk.KEY_End and \
                event.get_state() & Gdk.ModifierType.CONTROL_MASK:
            vadj.set_value(vadj.upper - vadj.page_size)

    def _smiley_button_cb(self, widget, event):
        self._show_smiley_window()

    def _send_button_cb(self, widget, event):
        self._entry_activate_cb(self._entry)

    def _entry_activate_cb(self, entry):
        self.chatbox._scroll_auto = True

        text = entry.props.text
        if text:
            logger.debug('Adding text to chatbox: %s: %s' % (self.owner, text))
            self.chatbox.add_text(self.owner, text)
            entry.props.text = ''
            if self.text_channel:
                logger.debug('sending to text_channel: %s' % (text))
                self.text_channel.send(text)
            else:
                logger.debug('Tried to send message but text channel '
                             'not connected.')

    def write_file(self, file_path):
        '''Store chat log in Journal.

        Handling the Journal is provided by Activity - we only need
        to define this method.
        '''
        logger.debug('write_file: writing %s' % file_path)
        self.chatbox.add_log_timestamp()
        f = open(file_path, 'w')
        try:
            f.write(self.chatbox.get_log())
        finally:
            f.close()
        self.metadata['mime_type'] = 'text/plain'

    def read_file(self, file_path):
        '''Load a chat log from the Journal.
        Handling the Journal is provided by Activity - we only need
        to define this method.
        '''
        logger.debug('read_file: reading %s' % file_path)
        log = open(file_path).readlines()
        last_line_was_timestamp = False
        for line in log:
            if line.endswith('\t\t\n'):
                if last_line_was_timestamp is False:
                    timestamp = line.strip().split('\t')[0]
                    self.chatbox.add_separator(timestamp)
                    last_line_was_timestamp = True
            else:
                timestamp, nick, color, status, text = line.strip().split('\t')
                status_message = bool(int(status))
                self.chatbox.add_text({
                    'nick': nick,
                    'color': color
                }, text, status_message)
                last_line_was_timestamp = False

    def play_sound(self, event):
        if _HAS_SOUND:
            SOUNDS_PATH = os.path.join(get_bundle_path(), 'sounds')
            SOUNDS = {
                'said_nick': os.path.join(SOUNDS_PATH, 'alert.wav'),
                'login': os.path.join(SOUNDS_PATH, 'login.wav'),
                'logout': os.path.join(SOUNDS_PATH, 'logout.wav')
            }

            self.element.set_state(Gst.State.NULL)
            self.element.set_property('uri', 'file://%s' % SOUNDS[event])
            self.element.set_state(Gst.State.PLAYING)

    def _create_smiley_window(self):
        grid = Gtk.Grid()
        width = int(Gdk.Screen.width() - 2 * style.GRID_CELL_SIZE)

        self._smiley_toolbar = SmileyToolbar(self)
        height = style.GRID_CELL_SIZE
        self._smiley_toolbar.set_size_request(width, height)
        grid.attach(self._smiley_toolbar, 0, 0, 1, 1)
        self._smiley_toolbar.show()

        self._smiley_table = Gtk.ScrolledWindow()
        self._smiley_table.set_policy(Gtk.PolicyType.NEVER,
                                      Gtk.PolicyType.AUTOMATIC)
        self._smiley_table.modify_bg(Gtk.StateType.NORMAL,
                                     style.COLOR_BLACK.get_gdk_color())
        if self._ebook_mode_detector.get_ebook_mode():
            height = int(Gdk.Screen.height() - 8 * style.GRID_CELL_SIZE)
        else:
            height = int(Gdk.Screen.height() - 4 * style.GRID_CELL_SIZE)
        self._smiley_table.set_size_request(width, height)

        table = self._create_smiley_table(width)
        self._smiley_table.add_with_viewport(table)
        table.show_all()

        grid.attach(self._smiley_table, 0, 1, 1, 1)
        self._smiley_table.show()

        self._smiley_window = Gtk.ScrolledWindow()
        self._smiley_window.set_policy(Gtk.PolicyType.NEVER,
                                       Gtk.PolicyType.NEVER)
        self._smiley_window.set_shadow_type(Gtk.ShadowType.ETCHED_IN)
        self._smiley_window.set_size_request(width, -1)

        self._smiley_window.add_with_viewport(grid)

        def _key_press_event_cb(widget, event):
            if event.keyval == Gdk.KEY_Escape:
                self._hide_smiley_window()
                return True
            return False

        self.connect('key-press-event', _key_press_event_cb)

        grid.show()

        self._fixed.put(self._smiley_window, style.GRID_CELL_SIZE, 0)

    def _show_smiley_window(self):
        if not hasattr(self, '_smiley_window'):
            self.busy()
            self._create_smiley_window()
        self._smiley_window.show()

    def _hide_smiley_window(self):
        if hasattr(self, '_smiley_window'):
            self._smiley_window.hide()
Ejemplo n.º 5
0
    def __init__(self, handle):
        pservice = presenceservice.get_instance()
        self.owner = pservice.get_owner()

        self._ebook_mode_detector = EbookModeDetector()

        self.chatbox = ChatBox(self.owner,
                               self._ebook_mode_detector.get_ebook_mode())
        self.chatbox.connect('open-on-journal', self.__open_on_journal)

        super(Chat, self).__init__(handle)

        self._entry = None
        self._has_alert = False
        self._has_osk = False

        self._setup_canvas()

        self._entry.grab_focus()

        toolbar_box = ToolbarBox()
        self.set_toolbar_box(toolbar_box)

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

        title_entry = TitleEntry(self)
        toolbar_box.toolbar.insert(title_entry, -1)
        title_entry.show()

        description_item = DescriptionItem(self)
        toolbar_box.toolbar.insert(description_item, -1)
        description_item.show()

        self._share_button = ShareButton(self)
        toolbar_box.toolbar.insert(self._share_button, -1)
        self._share_button.show()

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

        toolbar_box.toolbar.insert(StopButton(self), -1)
        toolbar_box.show_all()

        # Chat is room or one to one:
        self._chat_is_room = False
        self.text_channel = None

        if _HAS_SOUND:
            self.element = Gst.ElementFactory.make('playbin', 'Player')

        if self.shared_activity:
            # we are joining the activity following an invite
            self._entry.props.placeholder_text = \
                _('Please wait for a connection before starting to chat.')
            self.connect('joined', self._joined_cb)
            if self.get_shared():
                # we have already joined
                self._joined_cb(self)
        elif handle.uri:
            # XMPP non-sugar3 incoming chat, not sharable
            self._share_button.props.visible = False
            self._one_to_one_connection(handle.uri)
        else:
            # we are creating the activity
            if not self.metadata or self.metadata.get(
                    'share-scope', activity.SCOPE_PRIVATE) == \
                    activity.SCOPE_PRIVATE:
                # if we are in private session
                self._alert(_('Off-line'), _('Share, or invite someone.'))
            else:
                # resume of shared activity from journal object without invite
                self._entry.props.placeholder_text = \
                    _('Please wait for a connection before starting to chat.')
            self.connect('shared', self._shared_cb)
Ejemplo n.º 6
0
    def __init__(self, handle):
        pservice = presenceservice.get_instance()
        self.owner = pservice.get_owner()

        self._ebook_mode_detector = EbookModeDetector()

        self.chatbox = ChatBox(
            self.owner, self._ebook_mode_detector.get_ebook_mode())
        self.chatbox.connect('open-on-journal', self.__open_on_journal)

        super(Chat, self).__init__(handle)

        self._entry = None
        self._has_alert = False
        self._has_osk = False

        self._setup_canvas()

        self._entry.grab_focus()

        toolbar_box = ToolbarBox()
        self.set_toolbar_box(toolbar_box)

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

        title_entry = TitleEntry(self)
        toolbar_box.toolbar.insert(title_entry, -1)
        title_entry.show()

        description_item = DescriptionItem(self)
        toolbar_box.toolbar.insert(description_item, -1)
        description_item.show()

        self._share_button = ShareButton(self)
        toolbar_box.toolbar.insert(self._share_button, -1)
        self._share_button.show()

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

        toolbar_box.toolbar.insert(StopButton(self), -1)
        toolbar_box.show_all()

        # Chat is room or one to one:
        self._chat_is_room = False
        self.text_channel = None

        if _HAS_SOUND:
            self.element = Gst.ElementFactory.make('playbin', 'Player')

        if self.shared_activity:
            # we are joining the activity following an invite
            self._entry.props.placeholder_text = \
                _('Please wait for a connection before starting to chat.')
            self.connect('joined', self._joined_cb)
            if self.get_shared():
                # we have already joined
                self._joined_cb(self)
        elif handle.uri:
            # XMPP non-sugar3 incoming chat, not sharable
            self._share_button.props.visible = False
            self._one_to_one_connection(handle.uri)
        else:
            # we are creating the activity
            if not self.metadata or self.metadata.get(
                    'share-scope', activity.SCOPE_PRIVATE) == \
                    activity.SCOPE_PRIVATE:
                # if we are in private session
                self._alert(_('Off-line'), _('Share, or invite someone.'))
            else:
                # resume of shared activity from journal object without invite
                self._entry.props.placeholder_text = \
                    _('Please wait for a connection before starting to chat.')
            self.connect('shared', self._shared_cb)
Ejemplo n.º 7
0
class Chat(activity.Activity):

    def __init__(self, handle):
        pservice = presenceservice.get_instance()
        self.owner = pservice.get_owner()

        self._ebook_mode_detector = EbookModeDetector()

        self.chatbox = ChatBox(
            self.owner, self._ebook_mode_detector.get_ebook_mode())
        self.chatbox.connect('open-on-journal', self.__open_on_journal)

        super(Chat, self).__init__(handle)

        self._entry = None
        self._has_alert = False
        self._has_osk = False

        self._setup_canvas()

        self._entry.grab_focus()

        toolbar_box = ToolbarBox()
        self.set_toolbar_box(toolbar_box)

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

        title_entry = TitleEntry(self)
        toolbar_box.toolbar.insert(title_entry, -1)
        title_entry.show()

        description_item = DescriptionItem(self)
        toolbar_box.toolbar.insert(description_item, -1)
        description_item.show()

        self._share_button = ShareButton(self)
        toolbar_box.toolbar.insert(self._share_button, -1)
        self._share_button.show()

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

        toolbar_box.toolbar.insert(StopButton(self), -1)
        toolbar_box.show_all()

        # Chat is room or one to one:
        self._chat_is_room = False
        self.text_channel = None

        if _HAS_SOUND:
            self.element = Gst.ElementFactory.make('playbin', 'Player')

        if self.shared_activity:
            # we are joining the activity following an invite
            self._entry.props.placeholder_text = \
                _('Please wait for a connection before starting to chat.')
            self.connect('joined', self._joined_cb)
            if self.get_shared():
                # we have already joined
                self._joined_cb(self)
        elif handle.uri:
            # XMPP non-sugar3 incoming chat, not sharable
            self._share_button.props.visible = False
            self._one_to_one_connection(handle.uri)
        else:
            # we are creating the activity
            if not self.metadata or self.metadata.get(
                    'share-scope', activity.SCOPE_PRIVATE) == \
                    activity.SCOPE_PRIVATE:
                # if we are in private session
                self._alert(_('Off-line'), _('Share, or invite someone.'))
            else:
                # resume of shared activity from journal object without invite
                self._entry.props.placeholder_text = \
                    _('Please wait for a connection before starting to chat.')
            self.connect('shared', self._shared_cb)

    def _fixed_resize_cb(self, widget=None, rect=None):
        ''' If a toolbar opens or closes, we need to resize the vbox
        holding out scrolling window. '''
        if self._has_alert:
            dy = style.GRID_CELL_SIZE
        else:
            dy = 0
        if self._has_osk:
            if Gdk.Screen.width() > Gdk.Screen.height():
                dy += OSK_HEIGHT[0]
            else:
                dy += OSK_HEIGHT[1]

        self.chatbox.set_size_request(self._chat_width,
                                      self._chat_height - dy)
        self._fixed.move(self._entry_grid, style.GRID_CELL_SIZE,
                         self._chat_height - dy)

        self.chatbox.resize_conversation(dy)

    def _setup_canvas(self):
        ''' Create a canvas '''
        self._fixed = Gtk.Fixed()
        self._fixed.set_size_request(
            Gdk.Screen.width(), Gdk.Screen.height() - style.GRID_CELL_SIZE)
        self._fixed.connect('size-allocate', self._fixed_resize_cb)
        self.set_canvas(self._fixed)
        self._fixed.show()

        self._entry_widgets = self._make_entry_widgets()
        self._fixed.put(self.chatbox, 0, 0)
        self.chatbox.show()

        self._fixed.put(self._entry_grid, style.GRID_CELL_SIZE,
                        self._chat_height)
        self._entry_grid.show()

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

    def _configure_cb(self, event):
        self._fixed.set_size_request(
            Gdk.Screen.width(), Gdk.Screen.height() - style.GRID_CELL_SIZE)
        if self._ebook_mode_detector.get_ebook_mode():
            self._entry_height = int(style.GRID_CELL_SIZE * 1.5)
        else:
            self._entry_height = style.GRID_CELL_SIZE
        entry_width = Gdk.Screen.width() - \
            2 * (self._entry_height + style.GRID_CELL_SIZE)
        self._entry.set_size_request(entry_width, self._entry_height)
        self._entry_grid.set_size_request(
            Gdk.Screen.width() - 2 * style.GRID_CELL_SIZE,
            self._entry_height)

        self._chat_height = Gdk.Screen.height() - self._entry_height - \
            style.GRID_CELL_SIZE
        self._chat_width = Gdk.Screen.width()
        self.chatbox.set_size_request(self._chat_width, self._chat_height)
        self.chatbox.resize_all()

        width = int(Gdk.Screen.width() - 2 * style.GRID_CELL_SIZE)
        if self._ebook_mode_detector.get_ebook_mode():
            height = int(Gdk.Screen.height() - 8 * style.GRID_CELL_SIZE)
        else:
            height = int(Gdk.Screen.height() - 5 * style.GRID_CELL_SIZE)
        self._smiley_table.set_size_request(width, height)
        self._smiley_toolbar.set_size_request(width, -1)
        self._smiley_window.set_size_request(width, -1)

        self._fixed_resize_cb()

    def _create_smiley_table(self, width):
        pixel_size = (style.STANDARD_ICON_SIZE + style.LARGE_ICON_SIZE) / 2
        spacing = style.DEFAULT_SPACING
        button_size = pixel_size + spacing
        smilies_columns = int(width / button_size)
        pad = (width - smilies_columns * button_size) / 2

        table = Gtk.Grid()
        table.set_row_spacing(spacing)
        table.set_column_spacing(spacing)
        table.set_border_width(pad)

        queue = []

        def _create_smiley_icon_idle_cb():
            try:
                x, y, path, code = queue.pop()
            except IndexError:
                self.unbusy()
                return False
            pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(path,
                                                            pixel_size,
                                                            pixel_size)
            image = Gtk.Image.new_from_pixbuf(pixbuf)
            box = Gtk.EventBox()
            box.add(image)
            box.connect('button-press-event', self._add_smiley_to_entry, code)
            table.attach(box, x, y, 1, 1)
            box.show_all()
            return True

        x = 0
        y = 0
        smilies.init()
        for i in range(len(smilies.THEME)):
            path, hint, codes = smilies.THEME[i]
            queue.append([x, y, path, codes[0]])

            x += 1
            if x == smilies_columns:
                y += 1
                x = 0

        queue.reverse()
        GLib.idle_add(_create_smiley_icon_idle_cb)
        return table

    def _add_smiley_to_entry(self, icon, event, text):
        pos = self._entry.props.cursor_position
        self._entry.insert_text(text, pos)
        self._entry.grab_focus()
        self._entry.set_position(pos + len(text))
        self._hide_smiley_window()

    def _shared_cb(self, sender):
        self._setup()

    def _one_to_one_connection(self, tp_channel):
        '''Handle a private invite from a non-sugar3 XMPP client.'''
        if self.shared_activity or self.text_channel:
            return
        bus_name, connection, channel = json.loads(tp_channel)
        logger.debug('GOT XMPP: %s %s %s', bus_name, connection, channel)
        conn = TelepathyGLib.Connection.new(
            TelepathyGLib.DBusDaemon.dup(), bus_name, connection)
        self._one_to_one_connection_ready_cb(
            TelepathyGLib.DBusDaemon.dup(), bus_name, channel, conn)

    def _one_to_one_connection_ready_cb(self, bus_name, channel, conn):
        '''Callback for Connection for one to one connection'''
        text_channel = TelepathyGLib.Channel(conn, channel)
        self.text_channel = TextChannelWrapper(text_channel, conn)
        self.text_channel.set_received_callback(self._received_cb)
        self.text_channel.handle_pending_messages()
        self.text_channel.set_closed_callback(
            self._one_to_one_connection_closed_cb)
        self._chat_is_room = False
        self._alert(_('On-line'), _('Private Chat'))

        # XXX How do we detect the sender going offline?
        self._entry.set_sensitive(True)
        self._entry.props.placeholder_text = None
        self._entry.grab_focus()

    def _one_to_one_connection_closed_cb(self):
        '''Callback for when the text channel closes.'''
        self._alert(_('Off-line'), _('left the chat'))

    def _setup(self):
        self.text_channel = TextChannelWrapper(
            self.shared_activity.telepathy_text_chan,
            self.shared_activity.telepathy_conn)
        self.text_channel.set_received_callback(self._received_cb)
        self._alert(_('On-line'), _('Connected'))
        self.shared_activity.connect('buddy-joined', self._buddy_joined_cb)
        self.shared_activity.connect('buddy-left', self._buddy_left_cb)
        self._chat_is_room = True
        self._entry.set_sensitive(True)
        self._entry.props.placeholder_text = None
        self._entry.grab_focus()

    def _joined_cb(self, sender):
        '''Joined a shared activity.'''
        if not self.shared_activity:
            return
        logger.debug('Joined a shared chat')
        for buddy in self.shared_activity.get_joined_buddies():
            self._buddy_already_exists(buddy)
        self._setup()

    def _received_cb(self, buddy, text):
        '''Show message that was received.'''
        if buddy:
            if type(buddy) is dict:
                nick = buddy['nick']
            else:
                nick = buddy.props.nick
        else:
            nick = '???'
        logger.debug('Received message from %s: %s', nick, text)
        self.chatbox.add_text(buddy, text)

        if self.owner.props.nick in text:
            self.play_sound('said_nick')

        '''
        vscroll = self.chatbox.get_vadjustment()
        if vscroll.get_property('value') != vscroll.get_property('upper'):
            self._alert(_('New message'), _('New message from %s' % nick))
        '''
        if not self.has_focus:
            self.notify_user(_('Message from %s') % buddy, text)

    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_cancel_cb(self, alert, response_id):
        self.remove_alert(alert)
        self._has_alert = False
        self._fixed_resize_cb()

    def __open_on_journal(self, widget, url):
        '''Ask the journal to display a URL'''
        logger.debug('Create journal entry for URL: %s', url)
        jobject = datastore.create()
        metadata = {
            'title': '%s: %s' % (_('URL from Chat'), url),
            'title_set_by_user': '******',
            'icon-color': profile.get_color().to_string(),
            'mime_type': 'text/uri-list',
        }
        for k, v in metadata.items():
            jobject.metadata[k] = v
        file_path = os.path.join(get_activity_root(), 'instance',
                                 '%i_' % time.time())
        open(file_path, 'w').write(url + '\r\n')
        os.chmod(file_path, 0755)
        jobject.set_file_path(file_path)
        datastore.write(jobject)
        show_object_in_journal(jobject.object_id)
        jobject.destroy()
        os.unlink(file_path)

    def _buddy_joined_cb(self, sender, buddy):
        '''Show a buddy who joined'''
        if buddy == self.owner:
            return
        self.chatbox.add_text(
            buddy, _('%s joined the chat') % buddy.props.nick,
            status_message=True)

        self.play_sound('login')

    def _buddy_left_cb(self, sender, buddy):
        '''Show a buddy who joined'''
        if buddy == self.owner:
            return
        self.chatbox.add_text(
            buddy, _('%s left the chat') % buddy.props.nick,
            status_message=True)

        self.play_sound('logout')

    def _buddy_already_exists(self, buddy):
        '''Show a buddy already in the chat.'''
        if buddy == self.owner:
            return
        self.chatbox.add_text(
            buddy, _('%s is here') % buddy.props.nick,
            status_message=True)

    def can_close(self):
        '''Perform cleanup before closing.
        Close text channel of a one to one XMPP chat.
        '''
        if self._chat_is_room is False:
            if self.text_channel is not None:
                self.text_channel.close()
        return True

    def _make_entry_widgets(self):
        '''We need to create a button for the smiley, a text entry, and a
        send button.

        All of this, along with the chatbox, goes into a grid.

        ---------------------------------------
        | chat box                            |
        | smiley button | entry | send button |
        ---------------------------------------
        '''
        if self._ebook_mode_detector.get_ebook_mode():
            self._entry_height = int(style.GRID_CELL_SIZE * 1.5)
        else:
            self._entry_height = style.GRID_CELL_SIZE
        entry_width = Gdk.Screen.width() - \
            2 * (self._entry_height + style.GRID_CELL_SIZE)
        self._chat_height = Gdk.Screen.height() - self._entry_height - \
            style.GRID_CELL_SIZE
        self._chat_width = Gdk.Screen.width()

        self.chatbox.set_size_request(self._chat_width, self._chat_height)

        self._entry_grid = Gtk.Grid()
        self._entry_grid.set_size_request(
            Gdk.Screen.width() - 2 * style.GRID_CELL_SIZE,
            self._entry_height)

        smiley_button = EventIcon(icon_name='smilies',
                                  pixel_size=self._entry_height)
        smiley_button.connect('button-press-event', self._smiley_button_cb)
        self._entry_grid.attach(smiley_button, 0, 0, 1, 1)
        smiley_button.show()

        self._entry = Gtk.Entry()
        self._entry.set_size_request(entry_width, self._entry_height)
        self._entry.modify_bg(Gtk.StateType.INSENSITIVE,
                              style.COLOR_WHITE.get_gdk_color())
        self._entry.modify_base(Gtk.StateType.INSENSITIVE,
                                style.COLOR_WHITE.get_gdk_color())

        self._entry.set_sensitive(False)
        self._entry.props.placeholder_text = \
            _('You must be connected to a friend before starting to chat.')
        self._entry.connect('focus-in-event', self._entry_focus_in_cb)
        self._entry.connect('focus-out-event', self._entry_focus_out_cb)
        self._entry.connect('activate', self._entry_activate_cb)
        self._entry.connect('key-press-event', self._entry_key_press_cb)
        self._entry_grid.attach(self._entry, 1, 0, 1, 1)
        self._entry.show()

        send_button = EventIcon(icon_name='send',
                                pixel_size=self._entry_height)
        send_button.connect('button-press-event', self._send_button_cb)
        self._entry_grid.attach(send_button, 2, 0, 1, 1)
        send_button.show()

    def _get_icon_pixbuf(self, name):
        icon_theme = Gtk.IconTheme.get_default()
        icon_info = icon_theme.lookup_icon(
            name, style.LARGE_ICON_SIZE, 0)
        pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(
            icon_info.get_filename(), style.LARGE_ICON_SIZE,
            style.LARGE_ICON_SIZE)
        del icon_info
        return pixbuf

    def _entry_focus_in_cb(self, entry, event):
        self._hide_smiley_window()

        if self._ebook_mode_detector.get_ebook_mode():
            self._has_osk = True
            self._fixed_resize_cb()

    def _entry_focus_out_cb(self, entry, event):
        if self._ebook_mode_detector.get_ebook_mode():
            self._has_osk = False
            self._fixed_resize_cb()

    def _entry_key_press_cb(self, widget, event):
        '''Check for scrolling keys.

        Check if the user pressed Page Up, Page Down, Home or End and
        scroll the window according the pressed key.
        '''
        vadj = self.chatbox.get_vadjustment()
        if event.keyval == Gdk.KEY_Page_Down:
            value = vadj.get_value() + vadj.page_size
            if value > vadj.upper - vadj.page_size:
                value = vadj.upper - vadj.page_size
            vadj.set_value(value)
        elif event.keyval == Gdk.KEY_Page_Up:
            vadj.set_value(vadj.get_value() - vadj.page_size)
        elif event.keyval == Gdk.KEY_Home and \
                event.get_state() & Gdk.ModifierType.CONTROL_MASK:
            vadj.set_value(vadj.lower)
        elif event.keyval == Gdk.KEY_End and \
                event.get_state() & Gdk.ModifierType.CONTROL_MASK:
            vadj.set_value(vadj.upper - vadj.page_size)

    def _smiley_button_cb(self, widget, event):
        self._show_smiley_window()

    def _send_button_cb(self, widget, event):
        self._entry_activate_cb(self._entry)

    def _entry_activate_cb(self, entry):
        self.chatbox._scroll_auto = True

        text = entry.props.text
        if text:
            logger.debug('Adding text to chatbox: %s: %s' % (self.owner, text))
            self.chatbox.add_text(self.owner, text)
            entry.props.text = ''
            if self.text_channel:
                logger.debug('sending to text_channel: %s' % (text))
                self.text_channel.send(text)
            else:
                logger.debug('Tried to send message but text channel '
                             'not connected.')

    def write_file(self, file_path):
        '''Store chat log in Journal.

        Handling the Journal is provided by Activity - we only need
        to define this method.
        '''
        logger.debug('write_file: writing %s' % file_path)
        self.chatbox.add_log_timestamp()
        f = open(file_path, 'w')
        try:
            f.write(self.chatbox.get_log())
        finally:
            f.close()
        self.metadata['mime_type'] = 'text/plain'

    def read_file(self, file_path):
        '''Load a chat log from the Journal.
        Handling the Journal is provided by Activity - we only need
        to define this method.
        '''
        logger.debug('read_file: reading %s' % file_path)
        log = open(file_path).readlines()
        last_line_was_timestamp = False
        for line in log:
            if line.endswith('\t\t\n'):
                if last_line_was_timestamp is False:
                    timestamp = line.strip().split('\t')[0]
                    self.chatbox.add_separator(timestamp)
                    last_line_was_timestamp = True
            else:
                timestamp, nick, color, status, text = line.strip().split('\t')
                status_message = bool(int(status))
                self.chatbox.add_text({'nick': nick, 'color': color},
                                      text, status_message)
                last_line_was_timestamp = False

    def play_sound(self, event):
        if _HAS_SOUND:
            SOUNDS_PATH = os.path.join(get_bundle_path(), 'sounds')
            SOUNDS = {'said_nick': os.path.join(SOUNDS_PATH, 'alert.wav'),
                      'login': os.path.join(SOUNDS_PATH, 'login.wav'),
                      'logout': os.path.join(SOUNDS_PATH, 'logout.wav')}

            self.element.set_state(Gst.State.NULL)
            self.element.set_property('uri', 'file://%s' % SOUNDS[event])
            self.element.set_state(Gst.State.PLAYING)

    def _create_smiley_window(self):
        grid = Gtk.Grid()
        width = int(Gdk.Screen.width() - 2 * style.GRID_CELL_SIZE)

        self._smiley_toolbar = SmileyToolbar(self)
        height = style.GRID_CELL_SIZE
        self._smiley_toolbar.set_size_request(width, height)
        grid.attach(self._smiley_toolbar, 0, 0, 1, 1)
        self._smiley_toolbar.show()

        self._smiley_table = Gtk.ScrolledWindow()
        self._smiley_table.set_policy(Gtk.PolicyType.NEVER,
                                      Gtk.PolicyType.AUTOMATIC)
        self._smiley_table.modify_bg(
            Gtk.StateType.NORMAL, style.COLOR_BLACK.get_gdk_color())
        if self._ebook_mode_detector.get_ebook_mode():
            height = int(Gdk.Screen.height() - 8 * style.GRID_CELL_SIZE)
        else:
            height = int(Gdk.Screen.height() - 4 * style.GRID_CELL_SIZE)
        self._smiley_table.set_size_request(width, height)

        table = self._create_smiley_table(width)
        self._smiley_table.add_with_viewport(table)
        table.show_all()

        grid.attach(self._smiley_table, 0, 1, 1, 1)
        self._smiley_table.show()

        self._smiley_window = Gtk.ScrolledWindow()
        self._smiley_window.set_policy(Gtk.PolicyType.NEVER,
                                       Gtk.PolicyType.NEVER)
        self._smiley_window.set_shadow_type(Gtk.ShadowType.ETCHED_IN)
        self._smiley_window.set_size_request(width, -1)

        self._smiley_window.add_with_viewport(grid)

        def _key_press_event_cb(widget, event):
            if event.keyval == Gdk.KEY_Escape:
                self._hide_smiley_window()
                return True
            return False
        self.connect('key-press-event', _key_press_event_cb)

        grid.show()

        self._fixed.put(self._smiley_window, style.GRID_CELL_SIZE, 0)

    def _show_smiley_window(self):
        if not hasattr(self, '_smiley_window'):
            self.busy()
            self._create_smiley_window()
        self._smiley_window.show()

    def _hide_smiley_window(self):
        if hasattr(self, '_smiley_window'):
            self._smiley_window.hide()
Ejemplo n.º 8
0
    def __init__(self, handle):
        smilies.init()

        self.chatbox = ChatBox()

        super(ChatStudioSelf, self).__init__(handle)

        self.entry = None
        self.no_of_mistake = 0
        root = self.make_root()
        self.set_canvas(root)

        root.show_all()
        self.entry.grab_focus()
        self.score1 = 0
        self.accuracy = 0.0

        toolbar_box = ToolbarBox()
        self.set_toolbar_box(toolbar_box)
        toolbar_box.toolbar.insert(ActivityButton(self), -1)
        toolbar_box.toolbar.insert(TitleEntry(self), -1)
        try:
            from sugar.activity.widgets import DescriptionItem
        except ImportError:
            logger.debug("DescriptionItem button is not available, " "toolkit version < 0.96")
        else:
            description_item = DescriptionItem(self)
            toolbar_box.toolbar.insert(description_item, -1)
            description_item.show()

        StartLabel = gtk.Label(_("START: "))
        StartLabel.show()
        tool_item_StartLabel = gtk.ToolItem()
        tool_item_StartLabel.add(StartLabel)
        toolbar_box.toolbar.insert(tool_item_StartLabel, -1)
        tool_item_StartLabel.show()
        mc1 = MathCompEntry1(self)
        toolbar_box.toolbar.insert(mc1, -1)

        AddLabel = gtk.Label(_("  ADD: "))
        AddLabel.show()
        tool_item_AddLabel = gtk.ToolItem()
        tool_item_AddLabel.add(AddLabel)
        toolbar_box.toolbar.insert(tool_item_AddLabel, -1)
        tool_item_AddLabel.show()
        mc2 = MathCompEntry2(self)
        toolbar_box.toolbar.insert(mc2, -1)
        separator = gtk.SeparatorToolItem()
        toolbar_box.toolbar.insert(separator, -1)
        separator = gtk.SeparatorToolItem()
        toolbar_box.toolbar.insert(separator, -1)
        self._smiley = RadioMenuButton(icon_name="smilies")
        self._smiley.palette = Palette(_("Insert smiley"))
        self._smiley.props.sensitive = True
        # toolbar_box.toolbar.insert(self._smiley, -1)

        separator = gtk.SeparatorToolItem()
        separator.props.draw = False
        separator.set_expand(False)
        toolbar_box.toolbar.insert(separator, -1)
        scoreButton = ScoreButton(self)
        toolbar_box.toolbar.insert(scoreButton, -1)
        stopButton = StopButton(self)
        toolbar_box.toolbar.insert(stopButton, -1)
        toolbar_box.show_all()
        self.a1 = c1
        self.a2 = c2
        self.sum1 = self.a1 + self.a2
        pservice = presenceservice.get_instance()
        self.owner = pservice.get_owner()
        # Chat is room or one to one:
        self._chat_is_room = False
        self.text_channel = None

        if self.shared_activity:
            # we are joining the activity
            self.connect("joined", self._joined_cb)
            if self.get_shared():
                # we have already joined
                self._joined_cb(self)
        elif handle.uri:
            # XMPP non-Sugar incoming chat, not sharable
            share_button.props.visible = False
            self._one_to_one_connection(handle.uri)
        else:
            # we are creating the activity
            # if not self.metadata or self.metadata.get('share-scope',activity.SCOPE_PRIVATE) == activity.SCOPE_PRIVATE:
            # if we are in private session
            # self._alert(_('Off-line'), _('Share, or invite someone.'))
            self.connect("shared", self._shared_cb)
Ejemplo n.º 9
0
class ChatStudioSelf(activity.Activity):

    global score
    score = time.time()

    def __init__(self, handle):
        smilies.init()

        self.chatbox = ChatBox()

        super(ChatStudioSelf, self).__init__(handle)

        self.entry = None
        self.no_of_mistake = 0
        root = self.make_root()
        self.set_canvas(root)

        root.show_all()
        self.entry.grab_focus()
        self.score1 = 0
        self.accuracy = 0.0

        toolbar_box = ToolbarBox()
        self.set_toolbar_box(toolbar_box)
        toolbar_box.toolbar.insert(ActivityButton(self), -1)
        toolbar_box.toolbar.insert(TitleEntry(self), -1)
        try:
            from sugar.activity.widgets import DescriptionItem
        except ImportError:
            logger.debug("DescriptionItem button is not available, " "toolkit version < 0.96")
        else:
            description_item = DescriptionItem(self)
            toolbar_box.toolbar.insert(description_item, -1)
            description_item.show()

        StartLabel = gtk.Label(_("START: "))
        StartLabel.show()
        tool_item_StartLabel = gtk.ToolItem()
        tool_item_StartLabel.add(StartLabel)
        toolbar_box.toolbar.insert(tool_item_StartLabel, -1)
        tool_item_StartLabel.show()
        mc1 = MathCompEntry1(self)
        toolbar_box.toolbar.insert(mc1, -1)

        AddLabel = gtk.Label(_("  ADD: "))
        AddLabel.show()
        tool_item_AddLabel = gtk.ToolItem()
        tool_item_AddLabel.add(AddLabel)
        toolbar_box.toolbar.insert(tool_item_AddLabel, -1)
        tool_item_AddLabel.show()
        mc2 = MathCompEntry2(self)
        toolbar_box.toolbar.insert(mc2, -1)
        separator = gtk.SeparatorToolItem()
        toolbar_box.toolbar.insert(separator, -1)
        separator = gtk.SeparatorToolItem()
        toolbar_box.toolbar.insert(separator, -1)
        self._smiley = RadioMenuButton(icon_name="smilies")
        self._smiley.palette = Palette(_("Insert smiley"))
        self._smiley.props.sensitive = True
        # toolbar_box.toolbar.insert(self._smiley, -1)

        separator = gtk.SeparatorToolItem()
        separator.props.draw = False
        separator.set_expand(False)
        toolbar_box.toolbar.insert(separator, -1)
        scoreButton = ScoreButton(self)
        toolbar_box.toolbar.insert(scoreButton, -1)
        stopButton = StopButton(self)
        toolbar_box.toolbar.insert(stopButton, -1)
        toolbar_box.show_all()
        self.a1 = c1
        self.a2 = c2
        self.sum1 = self.a1 + self.a2
        pservice = presenceservice.get_instance()
        self.owner = pservice.get_owner()
        # Chat is room or one to one:
        self._chat_is_room = False
        self.text_channel = None

        if self.shared_activity:
            # we are joining the activity
            self.connect("joined", self._joined_cb)
            if self.get_shared():
                # we have already joined
                self._joined_cb(self)
        elif handle.uri:
            # XMPP non-Sugar incoming chat, not sharable
            share_button.props.visible = False
            self._one_to_one_connection(handle.uri)
        else:
            # we are creating the activity
            # if not self.metadata or self.metadata.get('share-scope',activity.SCOPE_PRIVATE) == activity.SCOPE_PRIVATE:
            # if we are in private session
            # self._alert(_('Off-line'), _('Share, or invite someone.'))
            self.connect("shared", self._shared_cb)

    def _shared_cb(self, sender):
        logger.debug("Chat was shared")
        self._setup()

    def _one_to_one_connection(self, tp_channel):
        """Handle a private invite from a non-Sugar XMPP client."""
        if self.shared_activity or self.text_channel:
            return
        bus_name, connection, channel = json.loads(tp_channel)
        logger.debug("GOT XMPP: %s %s %s", bus_name, connection, channel)
        Connection(
            bus_name,
            connection,
            ready_handler=lambda conn: self._one_to_one_connection_ready_cb(bus_name, channel, conn),
        )

    def _one_to_one_connection_ready_cb(self, bus_name, channel, conn):
        """Callback for Connection for one to one connection"""
        text_channel = Channel(bus_name, channel)
        self.text_channel = TextChannelWrapper(text_channel, conn)
        self.text_channel.set_received_callback(self._received_cb)
        self.text_channel.handle_pending_messages()
        self.text_channel.set_closed_callback(self._one_to_one_connection_closed_cb)
        self._chat_is_room = False
        self._alert(_("On-line"), _("Private Chat"))

        # XXX How do we detect the sender going offline?
        self.entry.set_sensitive(True)
        self.entry.grab_focus()

    def _one_to_one_connection_closed_cb(self):
        """Callback for when the text channel closes."""
        self._alert(_("Off-line"), _("left the chat"))

    def _setup(self):
        self.text_channel = TextChannelWrapper(
            self.shared_activity.telepathy_text_chan, self.shared_activity.telepathy_conn
        )
        self.text_channel.set_received_callback(self._received_cb)
        self._alert(_("On-line"), _("Connected"))
        self.shared_activity.connect("buddy-joined", self._buddy_joined_cb)
        self.shared_activity.connect("buddy-left", self._buddy_left_cb)
        self._chat_is_room = True
        self.entry.set_sensitive(True)
        self.entry.grab_focus()

    def _joined_cb(self, sender):
        """Joined a shared activity."""
        if not self.shared_activity:
            return
        logger.debug("Joined a shared chat")
        for buddy in self.shared_activity.get_joined_buddies():
            self._buddy_already_exists(buddy)
        self._setup()

    def _received_cb(self, buddy, text):
        """Show message that was received."""
        if buddy:
            if type(buddy) is dict:
                nick = buddy["nick"]
            else:
                nick = buddy.props.nick
        else:
            nick = "???"
        logger.debug("Received message from %s: %s", nick, text)
        self.chatbox.add_text(buddy, text)

    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)

    def _buddy_joined_cb(self, sender, buddy):
        """Show a buddy who joined"""
        if buddy == self.owner:
            return
        self.chatbox.add_text(buddy, buddy.props.nick + " " + _("joined the chat"), status_message=True)

    def _buddy_left_cb(self, sender, buddy):
        """Show a buddy who joined"""
        if buddy == self.owner:
            return
        self.chatbox.add_text(buddy, buddy.props.nick + " " + _("left the chat"), status_message=True)

    def _buddy_already_exists(self, buddy):
        """Show a buddy already in the chat."""
        if buddy == self.owner:
            return
        self.chatbox.add_text(buddy, buddy.props.nick + " " + _("is here"), status_message=True)

    def can_close(self):
        """Perform cleanup before closing. Close text channel of a one to one XMPP chat."""
        """ Create or Open csv file score_log """

        l = [[c1, c2, self.no_of_mistake, steps, self.accuracy]]

        with open("/home/labadmin/Activities/score_log.csv", "a+") as f:
            for row in l:
                for column in row:
                    f.write("%d\t\t " % column)
                f.write("\n")
            f.close()

        if self._chat_is_room is False:
            if self.text_channel is not None:
                self.text_channel.close()
        return True

    def make_root(self):
        entry = gtk.Entry()
        entry.modify_bg(gtk.STATE_INSENSITIVE, style.COLOR_WHITE.get_gdk_color())
        entry.modify_base(gtk.STATE_INSENSITIVE, style.COLOR_WHITE.get_gdk_color())
        entry.set_sensitive(True)
        entry.connect("activate", self.entry_activate_cb)
        entry.connect("key-press-event", self.entry_key_press_cb)
        self.entry = entry
        hbox = gtk.HBox()
        hbox.add(entry)
        box = gtk.VBox(homogeneous=False)
        box.pack_start(self.chatbox)
        box.pack_start(hbox, expand=False)
        return box

    def entry_key_press_cb(self, widget, event):
        """Check for scrolling keys.

        Check if the user pressed Page Up, Page Down, Home or End and
        scroll the window according the pressed key.
        """
        vadj = self.chatbox.get_vadjustment()
        if event.keyval == gtk.keysyms.Page_Down:
            value = vadj.get_value() + vadj.page_size
            if value > vadj.upper - vadj.page_size:
                value = vadj.upper - vadj.page_size
            vadj.set_value(value)
        elif event.keyval == gtk.keysyms.Page_Up:
            vadj.set_value(vadj.get_value() - vadj.page_size)
        elif event.keyval == gtk.keysyms.Home and event.state & gtk.gdk.CONTROL_MASK:
            vadj.set_value(vadj.lower)
        elif event.keyval == gtk.keysyms.End and event.state & gtk.gdk.CONTROL_MASK:
            vadj.set_value(vadj.upper - vadj.page_size)

    def entry_activate_cb(self, entry):
        strr = "Please enter a number."
        self.chatbox._scroll_auto = True
        text = entry.props.text
        logger.debug("Entry: %s" % text)
        while self.sum1 < 50:
            if text.isdigit():
                self.chatbox.add_text(self.owner, "Your ans")
                self.chatbox.add_text(self.owner, text)
                entry.props.text = ""
                self.connect(self.entry_ans_check_auto(text))
            else:
                self.chatbox.add_text(self.owner, strr)
            entry.props.text = ""
        self.chatbox.add_text(self.owner, "Game Over")
        global score
        self.chatbox.add_text(self.owner, "%.2f" % (time.time() - score))
        entry.props.text = ""

        # to evaluate the entered answer

    def entry_ans_check_auto(self, ans):
        global steps
        steps += 1
        self.chatbox.add_text(self.owner, "My ans")
        self.chatbox.add_text(self.owner, str(self.sum1))
        if self.sum1 == int(ans):
            self.accuracy += 10
        else:
            self.no_of_mistake += 1
            self.chatbox.add_text(self.owner, "No of steps" + str(steps))
        self.sum1 = self.sum1 + self.a2
        self.connect(self.entry_ans_check_auto(self.connect(self.entry_activate_cb())))

    def write_file(self, file_path):
        """Store chat log in Journal.

        Handling the Journal is provided by Activity - we only need
        to define this method.
        """
        logger.debug("write_file: writing %s" % file_path)
        self.chatbox.add_log_timestamp()
        f = open(file_path, "w")
        try:
            f.write(self.chatbox.get_log())
        finally:
            f.close()
        self.metadata["mime_type"] = "text/plain"

    def read_file(self, file_path):
        """Load a chat log from the Journal.

        Handling the Journal is provided by Activity - we only need
        to define this method.
        """
        logger.debug("read_file: reading %s" % file_path)
        log = open(file_path).readlines()
        last_line_was_timestamp = False
        for line in log:
            if line.endswith("\t\t\n"):
                if last_line_was_timestamp is False:
                    timestamp = line.strip().split("\t")[0]
                    self.chatbox.add_separator(timestamp)
                    last_line_was_timestamp = True
            else:
                timestamp, nick, color, status, text = line.strip().split("\t")
                status_message = bool(int(status))
                self.chatbox.add_text({"nick": nick, "color": color}, text, status_message)
                last_line_was_timestamp = False
Ejemplo n.º 10
0
class ChatStudioSelf(activity.Activity):

    def __init__(self, handle):
        """ 
	    __init__ function initializes the variables needed
        """
        self.chatbox = ChatBox()
        super(ChatStudioSelf, self).__init__(handle)
        self.entry = None
        root = self.make_root()
        self.set_canvas(root)
        root.show_all()
        self.entry.grab_focus()
	self.local_first_num = 0
	self.local_second_num = 0
	self.limit_num = 50
	self.calculated_sum = 0
	self.calculated_diff = 0
	self.second_attempt_flag = False
	self.metadata_dict = {}
	self.mode_of_game = ""
	self.game_metadata = False
	self.difficulty_level = "Easy"
	self.first_come_check = 0
	self.create_toolbar()
        self.entry.set_sensitive(False)
        pservice = presenceservice.get_instance()
        self.owner = pservice.get_owner()
        # Chat is room or one to one:
        self._chat_is_room = False

    def create_toolbar(self):
        """ 
	    This function creates the game toolbar
        """
        toolbar_box = ToolbarBox()
        self.set_toolbar_box(toolbar_box)
        toolbar_box.toolbar.insert(ActivityToolbarButton(self), -1)

        separator = gtk.SeparatorToolItem()
        separator.props.draw = False
        toolbar_box.toolbar.insert(separator, -1)

	scoreButton = ScoreButton(self)
	toolbar_box.toolbar.insert(scoreButton, -1)

        separator = gtk.SeparatorToolItem()
        separator.props.draw = False
        toolbar_box.toolbar.insert(separator, -1)

	self._modes = ToolComboBox()
        self._modelist = ['Select Mode', '+ Addition', '- Subtraction']
       	for i, f in enumerate(self._modelist):
         self._modes.combo.append_item(i, f) 
       	self.modes_handle_id = self._modes.combo.connect("changed", self._change_modes_toolbar)
        toolbar_box.toolbar.insert(self._modes, -1)
        self._modes.combo.set_active(0)

        separator = gtk.SeparatorToolItem()
        separator.props.draw = False
        toolbar_box.toolbar.insert(separator, -1)

	scorestats = VisualScore(self)
	toolbar_box.toolbar.insert(scorestats, -1)

        separator = gtk.SeparatorToolItem()
        separator.props.draw = False
        toolbar_box.toolbar.insert(separator, -1)

        separator = gtk.SeparatorToolItem()
        separator.props.draw = False
        toolbar_box.toolbar.insert(separator, -1)

	timestats = VisualTime(self)
	toolbar_box.toolbar.insert(timestats, -1)

        separator = gtk.SeparatorToolItem()
        separator.props.draw = False
        toolbar_box.toolbar.insert(separator, -1)

        separator = gtk.SeparatorToolItem()
        separator.props.draw = False
        separator.set_expand(True)
        toolbar_box.toolbar.insert(separator, -1)

	stopButton = StopButton(self)
	toolbar_box.toolbar.insert(stopButton, -1)
        toolbar_box.show_all()

    def _change_modes_toolbar(self, combo):
        """ 
	   This function is called when the mode of the game is selected.
        """
        response_id_of_modes_toolbar = combo.get_active()
	global global_first_num
	global global_second_num
	if (response_id_of_modes_toolbar == 1):
	 global_first_num = randint(5, 9)
	 global_second_num = randint(5, 9)
	 combo.set_sensitive(False)
	 self.local_first_num = global_first_num
	 self.local_second_num = global_second_num
	 self.calculated_sum = self.local_first_num + self.local_second_num
	 self.mode_of_game = "Addition"
	 global addition_mode
	 addition_mode = True
	 self.limit_num = 50
	 self.show_game_toolbar()

 	elif (response_id_of_modes_toolbar == 2):
	 global_first_num = randint(50, 55)
	 global_second_num = randint(5, 9)
	 combo.set_sensitive(False)
	 self.local_first_num = global_first_num
	 self.local_second_num = global_second_num
	 self.calculated_diff = self.local_first_num - self.local_second_num
	 self.mode_of_game = "Subtraction"
	 self.limit_num = 0
	 global subtraction_mode
	 subtraction_mode = True
	 self.show_game_toolbar()
        self.entry.set_sensitive(True)
        self.entry.grab_focus()


    def _setup(self):
        self.entry.set_sensitive(True)
        self.entry.grab_focus()

    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)

    def game_tools(self, title, text=None):
        """ 
	   This function creates instance of GameToolbar class.
        """
        game_opts = GameToolbar()
        game_opts.props.title = title
        game_opts.props.msg = text
        self.add_alert(game_opts)
        game_opts.connect('response', self.new_game)
        game_opts.show()

    def new_game(self, game_opt_tools, response_id):
        """ 
	   This function handles response of GameToolbar.
	   Generates numbers based on the button clicked
        """
	global steps
 	global no_of_mistake
	global accuracy
	global list_of_comp_ans
	global list_of_user_ans
	global gameComplete
	steps = 0
 	accuracy = 0.0
	no_of_mistake = 0
	self.first_come_check = 0
	gameComplete = False
	self.second_attempt_flag = False
	self.entry.set_sensitive(True)
        self.entry.grab_focus()
	del list_of_comp_ans[:]
	del list_of_user_ans[:]
	global scoretime
    	scoretime = time.time()
        self.remove_game_toolbar(game_opt_tools)
	global global_first_num
	global global_second_num
	self.chatbox.rem()
	if (response_id == 1):
	 self.difficulty_level = "Easy"
	 if addition_mode:
	  global_first_num = randint(5, 9)
	  global_second_num = randint(5, 9)
	  self.limit_num = 50
	 elif subtraction_mode:
	  global_first_num = randint(50, 59)
	  global_second_num = randint(5, 9)
	  self.limit_num = 0

	elif (response_id == 2):
	 self.difficulty_level = "Changed_Numbers"
	 messagedialog = gtk.MessageDialog(parent=None, flags=0,\
	  type=gtk.MESSAGE_QUESTION, buttons=gtk.BUTTONS_OK,\
	 message_format="Enter Numbers")
	 action_area = messagedialog.get_content_area()
	 start_lbl = gtk.Label("Start")
	 input_first_num_txtbox = gtk.Entry()
         input_first_num_txtbox.set_size_request(int(gtk.gdk.screen_width() / 25), -1)
	 if addition_mode:
	  mode_lbl = gtk.Label("+ Add")
	 elif subtraction_mode:
	  mode_lbl = gtk.Label("- Subtract")
	 input_second_num_txtbox = gtk.Entry()
         input_second_num_txtbox.set_size_request(int(gtk.gdk.screen_width() / 25), -1)

	 action_area.pack_start(start_lbl)
	 action_area.pack_start(input_first_num_txtbox)
	 action_area.pack_start(mode_lbl)
	 action_area.pack_start(input_second_num_txtbox)
	 messagedialog.show_all()
	 changed_num_resp = messagedialog.run()

         if changed_num_resp == gtk.RESPONSE_OK:
	  try:
       	   global_first_num = int(input_first_num_txtbox.get_text())
	   global_second_num = int(input_second_num_txtbox.get_text())
	   if subtraction_mode:
	    if (global_second_num > global_first_num):
		# raise BadNum("Num2 canot be greater than Num1")
		raise Exception
	  except Exception:
	   if addition_mode:
	    global_first_num = randint(5, 9)
	    global_second_num = randint(5, 9)
	    self.limit_num = 50
	   elif subtraction_mode:
	    global_first_num = randint(50, 59)
	    global_second_num = randint(5, 9)
	 messagedialog.destroy()

	elif(response_id == 3):
	 self.difficulty_level = "Easy"
	 easylistStartNum = [50, 52, 54, 55, 56, 51]
	 l1 = [6, 9, 3, 2]
	 l2 = [5, 10, 2]
	 l3 = [7, 8]
	 if addition_mode:
	  global_first_num = randint(1, 9)
	  global_second_num = global_first_num
 	  self.limit_num = 50
	 elif subtraction_mode:
	  global_first_num = choice(easylistStartNum)
	  if (global_first_num == 50):
	   global_second_num = choice(l2)
	  elif (global_first_num == 51):
	   global_second_num = 3
	  elif (global_first_num == 52):
	   global_second_num = 2
	  elif (global_first_num == 54):
	   global_second_num = choice(l1)
	  elif (global_first_num == 55):
	   global_second_num = 5
	  elif (global_first_num == 56):
	   global_second_num = choice(l3)

	elif(response_id == 4):
	 self.difficulty_level = "Medium"
	 l11 = [51, 52, 53, 54, 56, 57, 58, 59]
	 if addition_mode:
	  global_first_num = randint(2, 9)
	  global_second_num = randint(2, 9)
	  if (global_first_num == global_second_num):
	   global_second_num = randint(2, 9)
	  self.limit_num = 50
	 elif subtraction_mode:
	  global_first_num = choice(l11)
	  global_second_num = randint(2, 9)
	 if (global_first_num == global_second_num):
	   global_second_num = randint(2, 9)
	 
	elif(response_id == 5):
	 self.difficulty_level = "Hard"
	 if addition_mode:
	  global_first_num = randint(5, 10)
	  global_second_num = randint(5, 10)
	  self.limit_num = 100
	 elif subtraction_mode:
	  global_first_num = randint(100, 105)
	  global_second_num = randint(5, 9)

	self.local_first_num = global_first_num
	self.local_second_num = global_second_num
	global list_of_comp_ans
	if addition_mode:
	 self.calculated_sum = self.local_first_num + self.local_second_num
	 list_of_comp_ans.append(self.calculated_sum)

	if subtraction_mode:
	 self.calculated_diff = self.local_first_num - self.local_second_num
	 list_of_comp_ans.append(self.calculated_diff)
		
	self.show_game_toolbar()

    def remove_game_toolbar(self, alert):
        """ 
	   This function hides GameToolbar.
        """

	self.remove_alert(alert)

    def show_game_toolbar(self):
        """ 
	   This function displays GameToolbar.
        """

	self.chatbox.rem()
	if addition_mode:
         self.game_tools(_('\t\tStart : ' + \
         	str(global_first_num) + '\n\t\t+ Add\t: ' +\
         	str(global_second_num)), _(''))
	if subtraction_mode:
         self.game_tools(_('\t\tStart : ' + \
         	str(global_first_num) + '\n\t\t- Subtract\t: ' + \
         	str(global_second_num)), _(''))


    def make_root(self):
        entry = gtk.Entry()
        entry.modify_bg(gtk.STATE_INSENSITIVE, style.COLOR_WHITE.get_gdk_color())
        entry.modify_base(gtk.STATE_INSENSITIVE, style.COLOR_WHITE.get_gdk_color())
        entry.set_sensitive(True)
        entry.connect('activate', self.entry_activate_cb)
	entry.connect('key-press-event', self.entry_key_press_cb)
        self.entry = entry
        hbox = gtk.HBox()
        hbox.add(entry)
        box = gtk.VBox(homogeneous=False)
        box.pack_start(self.chatbox)
        box.pack_start(hbox, expand=False)
        return box


    def entry_key_press_cb(self, widget, event):
        """
	 Check for scrolling keys.
         Check if the user pressed Page Up, Page Down, Home or End and
         scroll the window according the pressed key.
        """
        vadj = self.chatbox.get_vadjustment()
        if event.keyval == gtk.keysyms.Page_Down:
            value = vadj.get_value() + vadj.page_size
            if value > vadj.upper - vadj.page_size:
                value = vadj.upper - vadj.page_size
            vadj.set_value(value)
        elif event.keyval == gtk.keysyms.Page_Up:
            vadj.set_value(vadj.get_value() - vadj.page_size)
        elif event.keyval == gtk.keysyms.Home and \
             event.state & gtk.gdk.CONTROL_MASK:
            vadj.set_value(vadj.lower)
        elif event.keyval == gtk.keysyms.End and \
             event.state & gtk.gdk.CONTROL_MASK:
            vadj.set_value(vadj.upper - vadj.page_size)

    def entry_activate_cb(self, entry):
        """ 
	   This function is triggered when user 
	   inputs some text to the chatbox.
	   Each input text is checked whether its a number or not.
	   If number, performs some actions, else prompts a message.
	   On Game Over, several actions which inlucde calculations
	   and saving/writing to files, also the entry is disabled.

        """

	msg_for_NaN = "Please enter a number."
	self.chatbox._scroll_auto = True
        text = entry.props.text
	logger.debug('Entry: %s' % text)
 	global scoretime
	global accuracy
	global gameComplete
	global list_of_comp_ans
	global list_of_user_ans
	if text.isdigit():
	 if addition_mode:
	  while (self.calculated_sum <= self.limit_num):
       	   entry.props.text = ''
   	   self.chatbox.add_text(self.owner, text)
	   list_of_user_ans.append(int(text))
	   self.connect(self.input_ans_check(text))
	   if (self.first_come_check == 0):
    	    scoretime = time.time()
	    self.first_come_check = 1
	 elif subtraction_mode:
	  while (self.calculated_diff >= 0):
   	   self.chatbox.add_text(self.owner, text)
       	   entry.props.text = ''
	   list_of_user_ans.append(text)
	   self.connect(self.input_ans_check(text))
	   if (self.first_come_check == 0):
    	    scoretime = time.time()
	    self.first_come_check = 1
	 self.calc_accuracy(no_of_mistake, steps)
	 scoretime = time.time() - scoretime
	 self.game_finish()
	 gameComplete = True
	 self.game_metadata = True
	 self.write_to_csv()
	 self.write_to_scorecard()
	 self.sort_score_file()
	 self.first_come_check += 1
	 entry.props.text = ''
   	 self.chatbox.add_text("Computer", "Game Over")
	 self.entry.set_sensitive(False)
	else:
	   self.chatbox.add_text(self.owner, msg_for_NaN)
        entry.props.text = ''

    # for evaluation for user ans
    def input_ans_check(self, ans):
         """ 
	   This function is called for every ans the user inputs.
	   for checking the answer.
	   If wrong, the user gets one chance to correct it.
         """

	 global steps
 	 global no_of_mistake
	 global accuracy
	 global list_of_comp_ans
	 global list_of_user_ans
	 msg = ''
	 if addition_mode:
	  correct_ans = self.calculated_sum
	 elif subtraction_mode:
	  correct_ans = self.calculated_diff
	 steps += 1
	 if (correct_ans == int(ans)):
	   accuracy += 10
	   msg = str(correct_ans)
	   if self.second_attempt_flag:
	    self.second_attempt_flag = False
	    msg = "Well done. Go ahead now."
	 else:
  	   no_of_mistake += 1
	   if self.second_attempt_flag:
	    msg = "Correct answer was "+ str(correct_ans) + " Go ahead now"
	    self.second_attempt_flag = False
	   else:
	    self.second_attempt_flag = True
	    msg = "Correct answer is "+ str(correct_ans) + " Please re-enter it"

   	 self.chatbox.add_text("Computer", msg)

	 if addition_mode and not self.second_attempt_flag:
	  self.calculated_sum = self.calculated_sum + self.local_second_num
	  list_of_comp_ans.append(self.calculated_sum)
	  self.second_attempt_flag = False

	 elif subtraction_mode and not self.second_attempt_flag:
	  self.calculated_diff = self.calculated_diff - self.local_second_num
	  self.second_attempt_flag = False
	  list_of_comp_ans.append(self.calculated_diff)

  	 self.connect(self.input_ans_check(self.connect(self.entry_activate_cb())))


    def calc_accuracy(self, mistakes_arg, steps_arg):
          """ 
	   This function calculates accuracy.
          """
	  global accuracy
	  accuracy = ((steps_arg - mistakes_arg) / float(steps_arg)) * 100
	  accuracy = int(accuracy * 100) / 100.0
	  accuracy = int(round(accuracy, 0))

    def game_finish(self):
        """ 
	   This function marks end of game
	   by displaying a splash screen kind of
	   with an image based on score and time played.
        """

	  top_lbl_in_dialog = ''
	  game_reply = gtk.Label()
	  game_details = gtk.Label()
	  img_on_game_finish = gtk.Image()
	  if (accuracy == 100):
	   top_lbl_in_dialog = "Game Over..!!"
	   game_reply.set_text("Excellent")
	   game_details.set_text("Accuracy: " + str(accuracy) + \
	   	"\nTime: " + str('%.1f' % scoretime))
	   img_on_game_finish.set_from_file("excellent.png")
	  elif (accuracy < 100 and accuracy >= 85):
	   top_lbl_in_dialog = "Game Over..!!"
	   game_reply.set_text("Great")
	   game_details.set_text("Accuracy: " + str(accuracy) + \
	   	"\nTime: " + str('%.1f' % scoretime))
	   img_on_game_finish.set_from_file("great.png")
	  elif (accuracy < 85 and accuracy > 0):
	   top_lbl_in_dialog = "Game Over..!!"
	   game_reply.set_text("Good")
	   game_details.set_text("Accuracy: " + str(accuracy) + \
	   	"\nTime: " + str('%.1f' % scoretime))
	   img_on_game_finish.set_from_file("good.png")
	  elif (accuracy == 0):
	   top_lbl_in_dialog = "Game Over..!!"
	   game_reply.set_text("Better Luck Next Time")
	   game_details.set_text("Accuracy: " + str(accuracy) + \
	   	"\nTime: " + str('%.1f' % scoretime))
	   img_on_game_finish.set_from_file("AC_0.png")

	  messagedialog = gtk.MessageDialog(parent=None, \
	  	flags=gtk.DIALOG_MODAL, type=gtk.MESSAGE_INFO, \
	  	buttons=gtk.BUTTONS_OK,message_format=top_lbl_in_dialog)
	  
	  messagedialog.modify_bg(gtk.STATE_NORMAL,gtk.gdk.color_parse('#00FFFF'))
	  
   	  messagedialog.set_image(img_on_game_finish)
	  action_area = messagedialog.get_content_area()

	  action_area.pack_start(game_reply)
	  action_area.pack_start(game_details)
	  messagedialog.show_all()
	  messagedialog.run()
	  messagedialog.destroy()
Ejemplo n.º 11
0
Archivo: activity.py Proyecto: i5o/chat
    def __init__(self, handle):
        smilies.init()
        self.chatbox = ChatBox()

        super(Chat, self).__init__(handle)

        self.entry = None

        root = self.make_root()
        self.set_canvas(root)
        root.show_all()
        self.entry.grab_focus()

        toolbar_box = ToolbarBox()
        self.set_toolbar_box(toolbar_box)
        toolbar_box.toolbar.insert(ActivityButton(self), -1)
        toolbar_box.toolbar.insert(TitleEntry(self), -1)

        try:
            from sugar.activity.widgets import DescriptionItem
        except ImportError:
            logger.debug('DescriptionItem button is not available, ' \
                   'toolkit version < 0.96')
        else:
            description_item = DescriptionItem(self)
            toolbar_box.toolbar.insert(description_item, -1)
            description_item.show()

        share_button = ShareButton(self)
        toolbar_box.toolbar.insert(share_button, -1)

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

        self._smiley = RadioMenuButton(icon_name='smilies')
        self._smiley.palette = Palette(_('Insert smiley'))
        self._smiley.props.sensitive = False
        toolbar_box.toolbar.insert(self._smiley, -1)

        table = self._create_pallete_smiley_table()
        table.show_all()
        self._smiley.palette.set_content(table)

        separator = gtk.SeparatorToolItem()
        separator.props.draw = False
        separator.set_expand(True)
        toolbar_box.toolbar.insert(separator, -1)

        toolbar_box.toolbar.insert(StopButton(self), -1)
        toolbar_box.show_all()

        pservice = presenceservice.get_instance()
        self.owner = pservice.get_owner()
        # Chat is room or one to one:
        self._chat_is_room = False
        self.text_channel = None

        if self.shared_activity:
            # we are joining the activity
            self.connect('joined', self._joined_cb)
            if self.get_shared():
                # we have already joined
                self._joined_cb(self)
        elif handle.uri:
            # XMPP non-Sugar incoming chat, not sharable
            share_button.props.visible = False
            self._one_to_one_connection(handle.uri)
        else:
            # we are creating the activity
            if not self.metadata or self.metadata.get('share-scope',
                    activity.SCOPE_PRIVATE) == activity.SCOPE_PRIVATE:
                # if we are in private session
                self._alert(_('Off-line'), _('Share, or invite someone.'))
            self.connect('shared', self._shared_cb)
Ejemplo n.º 12
0
Archivo: activity.py Proyecto: i5o/chat
class Chat(activity.Activity):

    def __init__(self, handle):
        smilies.init()
        self.chatbox = ChatBox()

        super(Chat, self).__init__(handle)

        self.entry = None

        root = self.make_root()
        self.set_canvas(root)
        root.show_all()
        self.entry.grab_focus()

        toolbar_box = ToolbarBox()
        self.set_toolbar_box(toolbar_box)
        toolbar_box.toolbar.insert(ActivityButton(self), -1)
        toolbar_box.toolbar.insert(TitleEntry(self), -1)

        try:
            from sugar.activity.widgets import DescriptionItem
        except ImportError:
            logger.debug('DescriptionItem button is not available, ' \
                   'toolkit version < 0.96')
        else:
            description_item = DescriptionItem(self)
            toolbar_box.toolbar.insert(description_item, -1)
            description_item.show()

        share_button = ShareButton(self)
        toolbar_box.toolbar.insert(share_button, -1)

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

        self._smiley = RadioMenuButton(icon_name='smilies')
        self._smiley.palette = Palette(_('Insert smiley'))
        self._smiley.props.sensitive = False
        toolbar_box.toolbar.insert(self._smiley, -1)

        table = self._create_pallete_smiley_table()
        table.show_all()
        self._smiley.palette.set_content(table)

        separator = gtk.SeparatorToolItem()
        separator.props.draw = False
        separator.set_expand(True)
        toolbar_box.toolbar.insert(separator, -1)

        toolbar_box.toolbar.insert(StopButton(self), -1)
        toolbar_box.show_all()

        pservice = presenceservice.get_instance()
        self.owner = pservice.get_owner()
        # Chat is room or one to one:
        self._chat_is_room = False
        self.text_channel = None

        if self.shared_activity:
            # we are joining the activity
            self.connect('joined', self._joined_cb)
            if self.get_shared():
                # we have already joined
                self._joined_cb(self)
        elif handle.uri:
            # XMPP non-Sugar incoming chat, not sharable
            share_button.props.visible = False
            self._one_to_one_connection(handle.uri)
        else:
            # we are creating the activity
            if not self.metadata or self.metadata.get('share-scope',
                    activity.SCOPE_PRIVATE) == activity.SCOPE_PRIVATE:
                # if we are in private session
                self._alert(_('Off-line'), _('Share, or invite someone.'))
            self.connect('shared', self._shared_cb)

    def _create_pallete_smiley_table(self):
        row_count = int(math.ceil(len(smilies.THEME) / float(SMILIES_COLUMNS)))
        table = gtk.Table(rows=row_count, columns=SMILIES_COLUMNS)
        index = 0

        for y in range(row_count):
            for x in range(SMILIES_COLUMNS):
                if index >= len(smilies.THEME):
                    break

                path, hint, codes = smilies.THEME[index]
                image = gtk.image_new_from_file(path)
                button = gtk.ToolButton(icon_widget=image)
                button.set_tooltip(gtk.Tooltips(), codes[0] + ' ' + hint)
                button.connect('clicked', self._add_smiley_to_entry, codes[0])
                table.attach(button, x, x + 1, y, y + 1)
                button.show()

                index = index + 1

        return table

    def _add_smiley_to_entry(self, button, text):
        self._smiley.palette.popdown(True)
        pos = self.entry.props.cursor_position
        self.entry.insert_text(text, pos)
        self.entry.grab_focus()
        self.entry.set_position(pos + len(text))

    def _shared_cb(self, sender):
        logger.debug('Chat was shared')
        self._setup()

    def _one_to_one_connection(self, tp_channel):
        """Handle a private invite from a non-Sugar XMPP client."""
        if self.shared_activity or self.text_channel:
            return
        bus_name, connection, channel = json.loads(tp_channel)
        logger.debug('GOT XMPP: %s %s %s', bus_name, connection,
                     channel)
        Connection(
            bus_name, connection, ready_handler=lambda conn: \
            self._one_to_one_connection_ready_cb(bus_name, channel, conn))

    def _one_to_one_connection_ready_cb(self, bus_name, channel, conn):
        """Callback for Connection for one to one connection"""
        text_channel = Channel(bus_name, channel)
        self.text_channel = TextChannelWrapper(text_channel, conn)
        self.text_channel.set_received_callback(self._received_cb)
        self.text_channel.handle_pending_messages()
        self.text_channel.set_closed_callback(
            self._one_to_one_connection_closed_cb)
        self._chat_is_room = False
        self._alert(_('On-line'), _('Private Chat'))

        # XXX How do we detect the sender going offline?
        self.entry.set_sensitive(True)
        self.entry.grab_focus()

    def _one_to_one_connection_closed_cb(self):
        """Callback for when the text channel closes."""
        self._alert(_('Off-line'), _('left the chat'))

    def _setup(self):
        self.text_channel = TextChannelWrapper(
            self.shared_activity.telepathy_text_chan,
            self.shared_activity.telepathy_conn)
        self.text_channel.set_received_callback(self._received_cb)
        self._alert(_('On-line'), _('Connected'))
        self.shared_activity.connect('buddy-joined', self._buddy_joined_cb)
        self.shared_activity.connect('buddy-left', self._buddy_left_cb)
        self._chat_is_room = True
        self.entry.set_sensitive(True)
        self.entry.grab_focus()
        self._smiley.props.sensitive = True

    def _joined_cb(self, sender):
        """Joined a shared activity."""
        if not self.shared_activity:
            return
        logger.debug('Joined a shared chat')
        for buddy in self.shared_activity.get_joined_buddies():
            self._buddy_already_exists(buddy)
        self._setup()

    def _received_cb(self, buddy, text):
        """Show message that was received."""
        if buddy:
            if type(buddy) is dict:
                nick = buddy['nick']
            else:
                nick = buddy.props.nick
        else:
            nick = '???'
        logger.debug('Received message from %s: %s', nick, text)
        self.chatbox.add_text(buddy, text)

    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)

    def _buddy_joined_cb(self, sender, buddy):
        """Show a buddy who joined"""
        if buddy == self.owner:
            return
        self.chatbox.add_text(buddy,
                buddy.props.nick + ' ' + _('joined the chat'),
                status_message=True)

    def _buddy_left_cb(self, sender, buddy):
        """Show a buddy who joined"""
        if buddy == self.owner:
            return
        self.chatbox.add_text(buddy,
                buddy.props.nick + ' ' + _('left the chat'),
                status_message=True)

    def _buddy_already_exists(self, buddy):
        """Show a buddy already in the chat."""
        if buddy == self.owner:
            return
        self.chatbox.add_text(buddy, buddy.props.nick + ' ' + _('is here'),
                status_message=True)

    def can_close(self):
        """Perform cleanup before closing.

        Close text channel of a one to one XMPP chat.

        """
        if self._chat_is_room is False:
            if self.text_channel is not None:
                self.text_channel.close()
        return True

    def make_root(self):
        entry = gtk.Entry()
        entry.modify_bg(gtk.STATE_INSENSITIVE,
                        style.COLOR_WHITE.get_gdk_color())
        entry.modify_base(gtk.STATE_INSENSITIVE,
                          style.COLOR_WHITE.get_gdk_color())
        entry.set_sensitive(False)
        entry.connect('activate', self.entry_activate_cb)
        entry.connect('key-press-event', self.entry_key_press_cb)
        self.entry = entry

        hbox = gtk.HBox()
        hbox.add(entry)

        box = gtk.VBox(homogeneous=False)
        box.pack_start(self.chatbox)
        box.pack_start(hbox, expand=False)

        return box

    def entry_key_press_cb(self, widget, event):
        """Check for scrolling keys.

        Check if the user pressed Page Up, Page Down, Home or End and
        scroll the window according the pressed key.
        """
        vadj = self.chatbox.get_vadjustment()
        if event.keyval == gtk.keysyms.Page_Down:
            value = vadj.get_value() + vadj.page_size
            if value > vadj.upper - vadj.page_size:
                value = vadj.upper - vadj.page_size
            vadj.set_value(value)
        elif event.keyval == gtk.keysyms.Page_Up:
            vadj.set_value(vadj.get_value() - vadj.page_size)
        elif event.keyval == gtk.keysyms.Home and \
             event.state & gtk.gdk.CONTROL_MASK:
            vadj.set_value(vadj.lower)
        elif event.keyval == gtk.keysyms.End and \
             event.state & gtk.gdk.CONTROL_MASK:
            vadj.set_value(vadj.upper - vadj.page_size)

    def entry_activate_cb(self, entry):
        self.chatbox._scroll_auto = True

        text = entry.props.text
        logger.debug('Entry: %s' % text)
        if text:
            self.chatbox.add_text(self.owner, text)
            entry.props.text = ''
            if self.text_channel:
                self.text_channel.send(text)
            else:
                logger.debug('Tried to send message but text channel '
                    'not connected.')

    def write_file(self, file_path):
        """Store chat log in Journal.

        Handling the Journal is provided by Activity - we only need
        to define this method.
        """
        logger.debug('write_file: writing %s' % file_path)
        self.chatbox.add_log_timestamp()
        f = open(file_path, 'w')
        try:
            f.write(self.chatbox.get_log())
        finally:
            f.close()
        self.metadata['mime_type'] = 'text/plain'

    def read_file(self, file_path):
        """Load a chat log from the Journal.

        Handling the Journal is provided by Activity - we only need
        to define this method.
        """
        logger.debug('read_file: reading %s' % file_path)
        log = open(file_path).readlines()
        last_line_was_timestamp = False
        for line in log:
            if line.endswith('\t\t\n'):
                if last_line_was_timestamp is False:
                    timestamp = line.strip().split('\t')[0]
                    self.chatbox.add_separator(timestamp)
                    last_line_was_timestamp = True
            else:
                timestamp, nick, color, status, text = line.strip().split('\t')
                status_message = bool(int(status))
                self.chatbox.add_text({'nick': nick, 'color': color},
                              text, status_message)
                last_line_was_timestamp = False
Ejemplo n.º 13
0
class Chat(activity.Activity):
    def __init__(self, handle):
        super(Chat, self).__init__(handle)

        smilies.init()

        self.entry = None
        self.chatbox = None

        root = self.make_root()
        self.set_canvas(root)
        root.show_all()
        self.entry.grab_focus()

        toolbar_box = ToolbarBox()
        self.set_toolbar_box(toolbar_box)
        toolbar_box.toolbar.insert(ActivityButton(self), -1)
        toolbar_box.toolbar.insert(TitleEntry(self), -1)

        share_button = ShareButton(self)
        toolbar_box.toolbar.insert(share_button, -1)

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

        self._smiley = RadioMenuButton(icon_name='smilies')
        self._smiley.palette = Palette(_('Insert smiley'))
        self._smiley.props.sensitive = False
        toolbar_box.toolbar.insert(self._smiley, -1)

        table = self._create_pallete_smiley_table()
        table.show_all()
        self._smiley.palette.set_content(table)

        separator = gtk.SeparatorToolItem()
        separator.props.draw = False
        separator.set_expand(True)
        toolbar_box.toolbar.insert(separator, -1)

        toolbar_box.toolbar.insert(StopButton(self), -1)
        toolbar_box.show_all()

        pservice = presenceservice.get_instance()
        self.owner = pservice.get_owner()
        # Chat is room or one to one:
        self._chat_is_room = False
        self.text_channel = None

        if self.shared_activity:
            # we are joining the activity
            self.connect('joined', self._joined_cb)
            if self.get_shared():
                # we have already joined
                self._joined_cb(self)
        elif handle.uri:
            # XMPP non-Sugar incoming chat, not sharable
            share_button.props.visible = False
            self._one_to_one_connection(handle.uri)
        else:
            # we are creating the activity
            if not self.metadata or self.metadata.get(
                    'share-scope',
                    activity.SCOPE_PRIVATE) == activity.SCOPE_PRIVATE:
                # if we are in private session
                self._alert(_('Off-line'), _('Share, or invite someone.'))
            self.connect('shared', self._shared_cb)

    def _create_pallete_smiley_table(self):
        row_count = int(math.ceil(len(smilies.THEME) / float(SMILIES_COLUMNS)))
        table = gtk.Table(rows=row_count, columns=SMILIES_COLUMNS)
        index = 0

        for y in range(row_count):
            for x in range(SMILIES_COLUMNS):
                if index >= len(smilies.THEME):
                    break

                path, hint, codes = smilies.THEME[index]
                image = gtk.image_new_from_file(path)
                button = gtk.ToolButton(icon_widget=image)
                button.set_tooltip(gtk.Tooltips(), codes[0] + ' ' + hint)
                button.connect('clicked', self._add_smiley_to_entry, codes[0])
                table.attach(button, x, x + 1, y, y + 1)
                button.show()

                index = index + 1

        return table

    def _add_smiley_to_entry(self, button, text):
        self._smiley.palette.popdown(True)
        pos = self.entry.props.cursor_position
        self.entry.insert_text(text, pos)
        self.entry.grab_focus()
        self.entry.set_position(pos + len(text))

    def _shared_cb(self, sender):
        logger.debug('Chat was shared')
        self._setup()

    def _one_to_one_connection(self, tp_channel):
        """Handle a private invite from a non-Sugar XMPP client."""
        if self.shared_activity or self.text_channel:
            return
        bus_name, connection, channel = cjson.decode(tp_channel)
        logger.debug('GOT XMPP: %s %s %s', bus_name, connection, channel)
        Connection(
            bus_name, connection, ready_handler=lambda conn: \
            self._one_to_one_connection_ready_cb(bus_name, channel, conn))

    def _one_to_one_connection_ready_cb(self, bus_name, channel, conn):
        """Callback for Connection for one to one connection"""
        text_channel = Channel(bus_name, channel)
        self.text_channel = TextChannelWrapper(text_channel, conn)
        self.text_channel.set_received_callback(self._received_cb)
        self.text_channel.handle_pending_messages()
        self.text_channel.set_closed_callback(
            self._one_to_one_connection_closed_cb)
        self._chat_is_room = False
        self._alert(_('On-line'), _('Private Chat'))

        # XXX How do we detect the sender going offline?
        self.entry.set_sensitive(True)
        self.entry.grab_focus()

    def _one_to_one_connection_closed_cb(self):
        """Callback for when the text channel closes."""
        self._alert(_('Off-line'), _('left the chat'))

    def _setup(self):
        self.text_channel = TextChannelWrapper(
            self.shared_activity.telepathy_text_chan,
            self.shared_activity.telepathy_conn)
        self.text_channel.set_received_callback(self._received_cb)
        self._alert(_('On-line'), _('Connected'))
        self.shared_activity.connect('buddy-joined', self._buddy_joined_cb)
        self.shared_activity.connect('buddy-left', self._buddy_left_cb)
        self._chat_is_room = True
        self.entry.set_sensitive(True)
        self.entry.grab_focus()
        self._smiley.props.sensitive = True

    def _joined_cb(self, sender):
        """Joined a shared activity."""
        if not self.shared_activity:
            return
        logger.debug('Joined a shared chat')
        for buddy in self.shared_activity.get_joined_buddies():
            self._buddy_already_exists(buddy)
        self._setup()

    def _received_cb(self, buddy, text):
        """Show message that was received."""
        if buddy:
            if type(buddy) is dict:
                nick = buddy['nick']
            else:
                nick = buddy.props.nick
        else:
            nick = '???'
        logger.debug('Received message from %s: %s', nick, text)
        self.chatbox.add_text(buddy, text)

    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)

    def _buddy_joined_cb(self, sender, buddy):
        """Show a buddy who joined"""
        if buddy == self.owner:
            return
        self.chatbox.add_text(buddy,
                              buddy.props.nick + ' ' + _('joined the chat'),
                              status_message=True)

    def _buddy_left_cb(self, sender, buddy):
        """Show a buddy who joined"""
        if buddy == self.owner:
            return
        self.chatbox.add_text(buddy,
                              buddy.props.nick + ' ' + _('left the chat'),
                              status_message=True)

    def _buddy_already_exists(self, buddy):
        """Show a buddy already in the chat."""
        if buddy == self.owner:
            return
        self.chatbox.add_text(buddy,
                              buddy.props.nick + ' ' + _('is here'),
                              status_message=True)

    def can_close(self):
        """Perform cleanup before closing.

        Close text channel of a one to one XMPP chat.

        """
        if self._chat_is_room is False:
            if self.text_channel is not None:
                self.text_channel.close()
        return True

    def make_root(self):
        entry = gtk.Entry()
        entry.modify_bg(gtk.STATE_INSENSITIVE,
                        style.COLOR_WHITE.get_gdk_color())
        entry.modify_base(gtk.STATE_INSENSITIVE,
                          style.COLOR_WHITE.get_gdk_color())
        entry.set_sensitive(False)
        entry.connect('activate', self.entry_activate_cb)
        self.entry = entry

        self.chatbox = ChatBox()

        hbox = gtk.HBox()
        hbox.add(entry)

        box = gtk.VBox(homogeneous=False)
        box.pack_start(self.chatbox)
        box.pack_start(hbox, expand=False)

        return box

    def entry_activate_cb(self, entry):
        text = entry.props.text
        logger.debug('Entry: %s' % text)
        if text:
            self.chatbox.add_text(self.owner, text)
            entry.props.text = ''
            if self.text_channel:
                self.text_channel.send(text)
            else:
                logger.debug('Tried to send message but text channel '
                             'not connected.')

    def write_file(self, file_path):
        """Store chat log in Journal.

        Handling the Journal is provided by Activity - we only need
        to define this method.
        """
        logger.debug('write_file: writing %s' % file_path)
        self.chatbox.add_log_timestamp()
        f = open(file_path, 'w')
        try:
            f.write(self.chatbox.get_log())
        finally:
            f.close()
        self.metadata['mime_type'] = 'text/plain'

    def read_file(self, file_path):
        """Load a chat log from the Journal.

        Handling the Journal is provided by Activity - we only need
        to define this method.
        """
        logger.debug('read_file: reading %s' % file_path)
        log = open(file_path).readlines()
        last_line_was_timestamp = False
        for line in log:
            if line.endswith('\t\t\n'):
                if last_line_was_timestamp is False:
                    timestamp = line.strip().split('\t')[0]
                    self.chatbox.add_separator(timestamp)
                    last_line_was_timestamp = True
            else:
                timestamp, nick, color, status, text = line.strip().split('\t')
                status_message = bool(int(status))
                self.chatbox.add_text({
                    'nick': nick,
                    'color': color
                }, text, status_message)
                last_line_was_timestamp = False