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 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 __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)
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()
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 __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)
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()
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)
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
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()
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)
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
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