def __init__(self, session, cid, update_window, members=None): '''constructor''' self.update_window = update_window self.session = session self.caches = e3.cache.CacheManager(self.session.config_dir.base_dir) self.emcache = self.caches.get_emoticon_cache( self.session.account.account) self.cid = float(cid) self.formatter = e3.common.MessageFormatter(session.contacts.me) self.first = True self._header_visible = True self._image_visible = True self._toolbar_visible = True self._message_waiting = True buffer_size = session.config.get_or_set("i_msg_history_size", 5) self.messages = RingBuffer(max=buffer_size) self.message_offset = 0 if members is None: self.members = [] else: self.members = members self._style = None # the base class should override this attributes self.info = None self.input = None self.output = None
def __init__(self, session, cid, update_window, members=None): '''constructor''' self.update_window = update_window self.session = session self.caches = e3.cache.CacheManager(self.session.config_dir.base_dir) self.emcache = self.caches.get_emoticon_cache(self.session.account.account) self.cid = float(cid) self.icid = self.cid self.formatter = e3.common.MessageFormatter() self._header_visible = True self._image_visible = True self._toolbar_visible = True self._message_waiting = False buffer_size = 10 self.messages = RingBuffer(max=buffer_size) self.message_offset = 0 if members is None: self.members = [] else: self.members = members self._style = None self.conv_status = ConversationStatus.ConversationStatus(self.session.config) # the base class should override this attributes self.info = None self.input = None self.output = None self.soundPlayer = extension.get_and_instantiate('sound', session)
def __init__(self, session, cid, update_window, members=None): '''constructor''' self.update_window = update_window self.session = session self.caches = e3.cache.CacheManager(self.session.config_dir.base_dir) self.emcache = self.caches.get_emoticon_cache(self.session.account.account) self.cid = float(cid) self.formatter = e3.common.MessageFormatter(session.contacts.me) self.first = True self._header_visible = True self._image_visible = True self._toolbar_visible = True self._message_waiting = True buffer_size = session.config.get_or_set("i_msg_history_size", 5) self.messages = RingBuffer(max=buffer_size) self.message_offset = 0 if members is None: self.members = [] else: self.members = members self._style = None # the base class should override this attributes self.info = None self.input = None self.output = None
def __init__(self, session, cid, update_window, members=None): '''constructor''' self.update_window = update_window self.session = session self.caches = self.session.caches self.emcache = self.caches.get_emoticon_cache( self.session.account.account) self.cid = float(cid) self.icid = self.cid self._header_visible = True self._image_visible = True self._toolbar_visible = True self._message_waiting = False buffer_size = 10 self.messages = RingBuffer(max=buffer_size) self.message_offset = 0 self.message_input = "" if members is None: self.members = [] else: self.members = members self._style = None self.conv_status = ConversationStatus.ConversationStatus( self.session.config) # the base class should override this attributes self.info = None self.header = None self.input = None self.output = None self.below_conversation = None self.soundPlayer = extension.get_and_instantiate('sound', session)
class Conversation(object): '''a widget that contains all the components inside''' def __init__(self, session, cid, update_window, members=None): '''constructor''' self.update_window = update_window self.session = session self.caches = e3.cache.CacheManager(self.session.config_dir.base_dir) self.emcache = self.caches.get_emoticon_cache(self.session.account.account) self.cid = float(cid) self.icid = self.cid self.formatter = e3.common.MessageFormatter() self._header_visible = True self._image_visible = True self._toolbar_visible = True self._message_waiting = False buffer_size = 10 self.messages = RingBuffer(max=buffer_size) self.message_offset = 0 self.message_input = "" if members is None: self.members = [] else: self.members = members self._style = None self.conv_status = ConversationStatus.ConversationStatus(self.session.config) # the base class should override this attributes self.info = None self.input = None self.output = None self.soundPlayer = extension.get_and_instantiate('sound', session) def subscribe_signals(self): ''' subscribes current session's signals ''' self.session.config.subscribe(self._on_avatarsize_changed, 'i_conv_avatar_size') self.session.config.subscribe(self._on_show_toolbar_changed, 'b_show_toolbar') self.session.config.subscribe(self._on_show_header_changed, 'b_show_header') self.session.config.subscribe(self._on_show_info_changed, 'b_show_info') self.session.config.subscribe(self._on_show_avatar_onleft, 'b_avatar_on_left') self.session.config.subscribe(self._on_icon_size_change, 'b_toolbar_small') self.session.signals.picture_change_succeed.subscribe( self.on_picture_change_succeed) self.session.signals.contact_attr_changed.subscribe( self.on_contact_attr_changed_succeed) self.session.signals.filetransfer_invitation.subscribe( self.on_filetransfer_invitation) self.session.signals.filetransfer_accepted.subscribe( self.on_filetransfer_accepted) self.session.signals.filetransfer_progress.subscribe( self.on_filetransfer_progress) self.session.signals.filetransfer_completed.subscribe( self.on_filetransfer_completed) self.session.signals.filetransfer_rejected.subscribe( self.on_filetransfer_rejected) self.session.signals.filetransfer_canceled.subscribe( self.on_filetransfer_canceled) self.session.signals.call_invitation.subscribe( self.on_call_invitation) self.session.signals.contact_block_succeed.subscribe( self.on_contact_block_succeed) self.session.signals.contact_unblock_succeed.subscribe( self.on_contact_unblock_succeed) def unsubscribe_signals(self): ''' unsubscribes current session's signals ''' self.session.config.unsubscribe(self._on_avatarsize_changed, 'i_conv_avatar_size') self.session.config.unsubscribe(self._on_show_toolbar_changed, 'b_show_toolbar') self.session.config.unsubscribe(self._on_show_header_changed, 'b_show_header') self.session.config.unsubscribe(self._on_show_info_changed, 'b_show_info') self.session.config.unsubscribe(self._on_show_avatar_onleft, 'b_avatar_on_left') self.session.config.unsubscribe(self._on_icon_size_change, 'b_toolbar_small') self.session.signals.picture_change_succeed.unsubscribe( self.on_picture_change_succeed) self.session.signals.contact_attr_changed.unsubscribe( self.on_contact_attr_changed_succeed) self.session.signals.filetransfer_invitation.unsubscribe( self.on_filetransfer_invitation) self.session.signals.filetransfer_accepted.unsubscribe( self.on_filetransfer_accepted) self.session.signals.filetransfer_progress.unsubscribe( self.on_filetransfer_progress) self.session.signals.filetransfer_completed.unsubscribe( self.on_filetransfer_completed) self.session.signals.filetransfer_rejected.unsubscribe( self.on_filetransfer_rejected) self.session.signals.filetransfer_canceled.unsubscribe( self.on_filetransfer_canceled) self.session.signals.call_invitation.unsubscribe( self.on_call_invitation) self.session.signals.contact_block_succeed.unsubscribe( self.on_contact_block_succeed) self.session.signals.contact_unblock_succeed.unsubscribe( self.on_contact_unblock_succeed) def _get_style(self): '''return the value of style''' return self._style def _set_style(self, style): '''set the value of style and update the style on input''' self._style = style self.session.config.font = style.font self.session.config.i_font_size = style.size self.session.config.b_font_bold = style.bold self.session.config.b_font_italic = style.italic self.session.config.b_font_underline = style.underline self.session.config.b_font_strike = style.strike self.session.config.font_color = '#' + style.color.to_hex() self.input.update_style(style) cstyle = property(fget=_get_style, fset=_set_style) def _load_style(self): '''load the default style from the configuration''' font = self.session.config.get_or_set("font", "Sans") font_color = self.session.config.get_or_set("font_color", "#000000") font_size = self.session.config.get_or_set("i_font_size", 10) font_bold = self.session.config.get_or_set("b_font_bold", False) font_italic = self.session.config.get_or_set("b_font_italic", False) font_underline = self.session.config.get_or_set("b_font_underline", False) font_strike = self.session.config.get_or_set("b_font_strike", False) if self.session.config.i_font_size < 6 or \ self.session.config.i_font_size > 32: font_size = self.session.config.i_font_size = 10 try: color = e3.Color.from_hex(font_color) except ValueError: font_color = self.session.config.font_color = '#000000' color = e3.Color.from_hex(font_color) self.cstyle = e3.Style(font, color, font_bold, font_italic, font_underline, font_strike, font_size) def get_preview(self, completepath): return None def on_font_selected(self, style): '''called when a new font is selected''' self.cstyle = style def on_color_selected(self, color): '''called when a new font is selected''' self.cstyle.color = color self.session.config.font_color = '#' + color.to_hex() self.input.update_style(self.cstyle) def on_style_selected(self, style): '''called when a new font is selected''' self.cstyle = style def on_invite(self, account): '''called when a contact is selected to be invited''' self.session.conversation_invite(self.cid, account) def on_filetransfer_invite(self, filename, completepath): '''called when a filetransfer is issued''' self.session.filetransfer_invite(self.cid, self.members[0], filename, completepath, self.get_preview(completepath)) def check_visible(self): ''' called by conversation manager to prevent hidden conversations from receiving messages ''' raise NotImplementedError def on_video_call(self): '''called when the user is requesting a video-only call''' raise NotImplementedError def on_toggle_avatar(self): '''hide or show the avatar bar''' # widget visibility is handled in _on_show_info_changed self.session.config.b_show_info = not self.session.config.b_show_info def on_voice_call(self): '''called when the user is requesting an audio-only call''' raise NotImplementedError def on_av_call(self): '''called when the user is requesting an audio-video call''' raise NotImplementedError def on_clean(self): '''called when the clean button is clicked''' self.output.clear() self.conv_status.clear() def _on_block_user_accept(self, accept, account): if accept == gui.stock.YES: self.session.block(account) def on_block_user(self): '''blocks the first user of the conversation''' account = self.members[0] contact = self.session.contacts.get(account) if contact is None: return if contact.blocked: self.session.unblock(account) else: dialog = extension.get_default('dialog') dialog.yes_no(_("Are you sure you want to block this contact?"), self._on_block_user_accept, account) def on_contact_block_succeed(self, account): if account == self.members[0]: self.set_sensitive(False, True) def on_contact_unblock_succeed(self, account): if account == self.members[0]: self.set_sensitive(True) def on_emote(self, emote): '''called when a emote is selected on the emote window''' self.input.append(emote) def on_notify_attention(self): '''called when the nudge button is clicked''' self.session.request_attention(self.cid) message = e3.Message(e3.Message.TYPE_NUDGE, '', None, None) message.body = _('You just sent a nudge!') msg = gui.Message.from_information(self.session.contacts.me, message) self.output.information(self.formatter, msg) self.conv_status.post_process_message(msg) self.play_nudge() def show(self): '''override the show method''' raise NotImplementedError("Method not implemented") def iconify(self): '''override the iconify method''' raise NotImplementedError("Method not implemented") def update_message_waiting(self, is_waiting): """ update the information on the conversation to inform if a message is waiting is_waiting -- boolean value that indicates if a message is waiting """ raise NotImplementedError("Method not implemented") def update_single_information(self, nick, message, account): """ update the information for a conversation with a single user nick -- the nick of the other account (escaped) message -- the message of the other account (escaped) account -- the account """ raise NotImplementedError("Method not implemented") def update_group_information(self): """ update the information for a conversation with multiple users """ raise NotImplementedError("Method not implemented") def set_sensitive(self, is_sensitive, force_sensitive_block_button=False): """ used to make the conversation insensitive while the conversation is still open while the user is disconnected and to set it back to sensitive when the user is reconnected """ raise NotImplementedError("Method not implemented") def set_image_visible(self, is_visible): """ set the visibility of the widget that displays the images of the members is_visible -- boolean that says if the message should be shown or hidden """ raise NotImplementedError("Method not implemented") def set_header_visible(self, is_visible): ''' hide or show the widget according to is_visible is_visible -- boolean that says if the widget should be shown or hidden ''' raise NotImplementedError("Method not implemented") def set_toolbar_visible(self, is_visible): ''' hide or show the widget according to is_visible is_visible -- boolean that says if the widget should be shown or hidden ''' raise NotImplementedError("Method not implemented") def input_grab_focus(self): ''' sets the focus on the input widget ''' raise NotImplementedError("Method not implemented") def on_close(self): '''called when the conversation is closed''' raise NotImplementedError("Method not implemented") def _get_message_waiting(self): '''return True if a message is waiting''' return self._message_waiting def _set_message_waiting(self, value): '''set the value of message waiting, update the gui to reflect the value''' self._message_waiting = value self.update_message_waiting(value) message_waiting = property(fget=_get_message_waiting, fset=_set_message_waiting) def _get_group_chat(self): '''return True if the conversation contains more than one member, false otherwise''' return len(self.members) > 1 is_group_chat = property(fget=_get_group_chat) def _send_typing_notification(self): '''method called to send typing notifications''' self.session.send_typing_notification(self.cid) def output_message(self, message, cedict): '''display current outgoing message into OutputText''' msg = self.conv_status.pre_process_message(self.session.contacts.me, message, False, cedict, self.emcache.path, message.timestamp, message.type, self.cstyle) self.output.send_message(self.formatter, msg) self.conv_status.post_process_message(msg) def _on_send_message(self, text): '''method called when the user press enter on the input text''' cedict = self.emcache.parse() custom_emoticons = gui.base.MarkupParser.get_custom_emotes(text, cedict) self.session.send_message(self.cid, text, self.cstyle, cedict, custom_emoticons) message = e3.Message(e3.Message.TYPE_MESSAGE, text, None, self.cstyle) self.output_message(message, cedict) self.messages.push(text) self.reset_message_offset() self.play_send() self.conv_status.update_status() def input_message(self, message, contact, cedict, cepath): '''display current ingoing message into OutputText''' msg = self.conv_status.pre_process_message(contact, message, True, cedict, cepath, message.timestamp, message.type, message.style) self.output.receive_message(self.formatter, msg) self.conv_status.post_process_message(msg) def on_receive_message(self, message, account, received_custom_emoticons): '''method called when a message arrives to the conversation''' contact = self.session.contacts.safe_get(account) if message.type == e3.Message.TYPE_MESSAGE or \ message.type == e3.Message.TYPE_FLNMSG: if self.session.config.b_override_text_color: message.style.color = \ e3.base.Color.from_hex(self.session.config.override_text_color) user_emcache = self.caches.get_emoticon_cache(account) #XXX: when we send messages from the web iface we get those here, so show them propertly if contact.account == self.session.contacts.me.account: self.output_message(message, None) return self.input_message(message, contact, received_custom_emoticons, user_emcache.path) self.play_type() elif message.type == e3.Message.TYPE_NUDGE: message.body = _('%s just sent you a nudge!') % (contact.display_name,) msg = gui.Message.from_information(contact, message) self.output.information(self.formatter, msg) self.conv_status.post_process_message(msg) self.play_nudge() elif message.type == e3.Message.TYPE_INFO: msg = gui.Message.from_information(contact, message) self.output.information(self.formatter, msg) self.conv_status.post_process_message(msg) self.conv_status.update_status() def on_send_message_failed(self, errorCode): '''method called when a message fails to be delivered''' contact = self.session.contacts.me message = e3.Message(e3.Message.TYPE_MESSAGE, '', None, None) message.body = _('Error delivering message') msg = gui.Message.from_information(contact, message) self.output.information(self.formatter, msg) self.conv_status.post_process_message(msg) self.conv_status.update_status() def on_user_typing(self, account): '''method called when a someone is typing''' raise NotImplementedError def _get_icon(self): '''return the icon that represent the current status of the conversation (the status of the contact on a single conversation, a group icon on group chat or a waiting icon) ''' if self.message_waiting: icon = gui.theme.image_theme.new_message elif self.is_group_chat: icon = gui.theme.image_theme.group_chat elif len(self.members) == 1: contact = self.session.contacts.get(self.members[0]) # can be false if we are un a group chat with someone we dont # have and the last contact leaves.. if contact: stat = contact.status else: stat = e3.status.ONLINE icon = gui.theme.image_theme.status_icons.get(stat, e3.status.OFFLINE) else: log.debug('unknown state on Conversation._get_icon') return gui.theme.image_theme.connect return icon icon = property(fget=_get_icon) def _get_text(self): '''return the text that represent the conversation title''' if self.is_group_chat: text = _('Group chat') elif len(self.members) == 1: contact = self.session.contacts.safe_get(self.members[0]) text = contact.display_name else: log.debug('unknown state on Conversation._get_text') text = '(?)' return text text = property(fget=_get_text) def update_data(self): '''update the data on the conversation''' if len(self.members) == 1: self._update_single_information(self.members[0]) elif len(self.members) > 1: self.update_group_information() def update_p2p(self, account, _type, *what): ''' update the p2p data in the conversation (custom emoticons) ''' self.output.update_p2p(account, _type, *what) def on_contact_joined(self, account): '''called when a contact joins the conversation''' if account not in self.members: self.members.append(account) contact = self.session.contacts.safe_get(account) if len(self.members) > 1: message = e3.base.Message(e3.base.Message.TYPE_MESSAGE, \ _('%s has joined the conversation') % (contact.display_name), \ account) msg = gui.Message.from_information(contact, message) self.output.information(self.formatter, msg) self.conv_status.post_process_message(msg) self.update_data() def on_contact_left(self, account): '''called when a contact leaves the conversation''' if len(self.members) > 1 and account in self.members: self.members.remove(account) self.update_data() contact = self.session.contacts.safe_get(account) message = e3.base.Message(e3.base.Message.TYPE_MESSAGE, \ _('%s has left the conversation') % (contact.display_name), \ account) msg = gui.Message.from_information(contact, message) self.output.information(self.formatter, msg) self.conv_status.post_process_message(msg) def on_group_started(self): '''called when a group conversation starts''' self.update_data() def on_group_ended(self): '''called when a group conversation ends''' self.update_data() def _update_single_information(self, account): '''set the data of the conversation to the data of the account''' contact = self.session.contacts.safe_get(account) if contact.media == '': message = MarkupParser.escape(contact.message) else: message = MarkupParser.escape(contact.media) nick = MarkupParser.escape(contact.display_name) self.update_single_information(nick, message, account) def _set_image_visible(self, value): '''hide or show the widget according to value''' self.set_image_visible(value) self._image_visible = value def _get_image_visible(self): '''return the value of image_visible''' return self._image_visible image_visible = property(fget=_get_image_visible, fset=_set_image_visible) def _set_header_visible(self, value): '''hide or show the widget according to value''' self.set_header_visible(value) self._header_visible = value def _get_header_visible(self): '''return the value of _header_visible''' return self._header_visible header_visible = property(fget=_get_header_visible, fset=_set_header_visible) def _set_toolbar_visible(self, value): '''hide or show the widget according to value''' self.set_toolbar_visible(value) self._toolbar_visible = value def _get_toolbar_visible(self): '''return the value of image_visible''' return self._toolbar_visible toolbar_visible = property(fget=_get_toolbar_visible, fset=_set_toolbar_visible) def play_nudge(self): """ play the nudge sound """ if self.session.config.b_play_nudge: self.soundPlayer.play(gui.theme.sound_theme.sound_nudge) def play_send(self): """ play the send sound """ if self.session.config.b_play_send: self.soundPlayer.play(gui.theme.sound_theme.sound_send) def play_type(self): """ play the receive sound """ if self.session.config.b_play_type and (self.message_waiting or not \ self.session.config.b_mute_sounds_when_focussed): self.soundPlayer.play(gui.theme.sound_theme.sound_type) def cycle_history(self, change=-1): """ return one of the last N messages sent, the one returned is the one pointed by message_offset, every time you call this function it will go to the previous one, you can reset it using reset_message_offset. change is the direction of cycling, 1 will go forward -1 will go backwards if no message in the buffer return an empty string if there is message before cycling, it will be stored till the message sent """ if change < 0 and self.message_offset == 0: self.message_input = self.input.text self.message_offset += change if abs(self.message_offset) + 1 > len(self.messages): self.message_offset=1 - len(self.messages) if self.message_offset > 0: self.reset_message_offset() try: if self.message_offset == 0: self.input.text = self.message_input else: self.input.text = self.messages.peak(self.message_offset) except IndexError: pass def reset_message_offset(self): self.message_offset = 0 def _member_to_contact(self,member): return self.session.contacts.safe_get(member) def steal_emoticon(self, uri): """ receives the path or the uri for the emoticon to be added """ raise NotImplementedError("Method not implemented")
class Conversation(object): '''a widget that contains all the components inside''' def __init__(self, session, cid, update_window, members=None): '''constructor''' self.update_window = update_window self.session = session self.caches = e3.cache.CacheManager(self.session.config_dir.base_dir) self.emcache = self.caches.get_emoticon_cache( self.session.account.account) self.cid = float(cid) self.icid = self.cid self.formatter = e3.common.MessageFormatter() self._header_visible = True self._image_visible = True self._toolbar_visible = True self._message_waiting = False buffer_size = 10 self.messages = RingBuffer(max=buffer_size) self.message_offset = 0 self.message_input = "" if members is None: self.members = [] else: self.members = members self._style = None self.conv_status = ConversationStatus.ConversationStatus( self.session.config) # the base class should override this attributes self.info = None self.input = None self.output = None self.soundPlayer = extension.get_and_instantiate('sound', session) def subscribe_signals(self): ''' subscribes current session's signals ''' self.session.config.subscribe(self._on_avatarsize_changed, 'i_conv_avatar_size') self.session.config.subscribe(self._on_show_toolbar_changed, 'b_show_toolbar') self.session.config.subscribe(self._on_show_header_changed, 'b_show_header') self.session.config.subscribe(self._on_show_info_changed, 'b_show_info') self.session.config.subscribe(self._on_show_avatar_onleft, 'b_avatar_on_left') self.session.config.subscribe(self._on_icon_size_change, 'b_toolbar_small') self.session.signals.picture_change_succeed.subscribe( self.on_picture_change_succeed) self.session.signals.contact_attr_changed.subscribe( self.on_contact_attr_changed_succeed) self.session.signals.filetransfer_invitation.subscribe( self.on_filetransfer_invitation) self.session.signals.filetransfer_accepted.subscribe( self.on_filetransfer_accepted) self.session.signals.filetransfer_progress.subscribe( self.on_filetransfer_progress) self.session.signals.filetransfer_completed.subscribe( self.on_filetransfer_completed) self.session.signals.filetransfer_rejected.subscribe( self.on_filetransfer_rejected) self.session.signals.filetransfer_canceled.subscribe( self.on_filetransfer_canceled) self.session.signals.call_invitation.subscribe(self.on_call_invitation) self.session.signals.contact_block_succeed.subscribe( self.on_contact_block_succeed) self.session.signals.contact_unblock_succeed.subscribe( self.on_contact_unblock_succeed) def unsubscribe_signals(self): ''' unsubscribes current session's signals ''' self.session.config.unsubscribe(self._on_avatarsize_changed, 'i_conv_avatar_size') self.session.config.unsubscribe(self._on_show_toolbar_changed, 'b_show_toolbar') self.session.config.unsubscribe(self._on_show_header_changed, 'b_show_header') self.session.config.unsubscribe(self._on_show_info_changed, 'b_show_info') self.session.config.unsubscribe(self._on_show_avatar_onleft, 'b_avatar_on_left') self.session.config.unsubscribe(self._on_icon_size_change, 'b_toolbar_small') self.session.signals.picture_change_succeed.unsubscribe( self.on_picture_change_succeed) self.session.signals.contact_attr_changed.unsubscribe( self.on_contact_attr_changed_succeed) self.session.signals.filetransfer_invitation.unsubscribe( self.on_filetransfer_invitation) self.session.signals.filetransfer_accepted.unsubscribe( self.on_filetransfer_accepted) self.session.signals.filetransfer_progress.unsubscribe( self.on_filetransfer_progress) self.session.signals.filetransfer_completed.unsubscribe( self.on_filetransfer_completed) self.session.signals.filetransfer_rejected.unsubscribe( self.on_filetransfer_rejected) self.session.signals.filetransfer_canceled.unsubscribe( self.on_filetransfer_canceled) self.session.signals.call_invitation.unsubscribe( self.on_call_invitation) self.session.signals.contact_block_succeed.unsubscribe( self.on_contact_block_succeed) self.session.signals.contact_unblock_succeed.unsubscribe( self.on_contact_unblock_succeed) def _get_style(self): '''return the value of style''' return self._style def _set_style(self, style): '''set the value of style and update the style on input''' self._style = style self.session.config.font = style.font self.session.config.i_font_size = style.size self.session.config.b_font_bold = style.bold self.session.config.b_font_italic = style.italic self.session.config.b_font_underline = style.underline self.session.config.b_font_strike = style.strike self.session.config.font_color = '#' + style.color.to_hex() self.input.update_style(style) cstyle = property(fget=_get_style, fset=_set_style) def _load_style(self): '''load the default style from the configuration''' font = self.session.config.get_or_set("font", "Sans") font_color = self.session.config.get_or_set("font_color", "#000000") font_size = self.session.config.get_or_set("i_font_size", 10) font_bold = self.session.config.get_or_set("b_font_bold", False) font_italic = self.session.config.get_or_set("b_font_italic", False) font_underline = self.session.config.get_or_set( "b_font_underline", False) font_strike = self.session.config.get_or_set("b_font_strike", False) if self.session.config.i_font_size < 6 or \ self.session.config.i_font_size > 32: font_size = self.session.config.i_font_size = 10 try: color = e3.Color.from_hex(font_color) except ValueError: font_color = self.session.config.font_color = '#000000' color = e3.Color.from_hex(font_color) self.cstyle = e3.Style(font, color, font_bold, font_italic, font_underline, font_strike, font_size) def get_preview(self, completepath): return None def on_font_selected(self, style): '''called when a new font is selected''' self.cstyle = style def on_color_selected(self, color): '''called when a new font is selected''' self.cstyle.color = color self.session.config.font_color = '#' + color.to_hex() self.input.update_style(self.cstyle) def on_invite(self, account): '''called when a contact is selected to be invited''' self.session.conversation_invite(self.cid, account) def on_filetransfer_invite(self, filename, completepath): '''called when a filetransfer is issued''' self.session.filetransfer_invite(self.cid, self.members[0], filename, completepath, self.get_preview(completepath)) def check_visible(self): ''' called by conversation manager to prevent hidden conversations from receiving messages ''' raise NotImplementedError def on_video_call(self): '''called when the user is requesting a video-only call''' raise NotImplementedError def on_toggle_avatar(self): '''hide or show the avatar bar''' # widget visibility is handled in _on_show_info_changed self.session.config.b_show_info = not self.session.config.b_show_info def on_voice_call(self): '''called when the user is requesting an audio-only call''' raise NotImplementedError def on_av_call(self): '''called when the user is requesting an audio-video call''' raise NotImplementedError def on_clean(self): '''called when the clean button is clicked''' self.output.clear() self.conv_status.clear() def _on_block_user_accept(self, accept, account): if accept == gui.stock.YES: self.session.block(account) def on_block_user(self): '''blocks the first user of the conversation''' account = self.members[0] contact = self.session.contacts.get(account) if contact is None: return if contact.blocked: self.session.unblock(account) else: dialog = extension.get_default('dialog') dialog.yes_no(_("Are you sure you want to block this contact?"), self._on_block_user_accept, account) def on_contact_block_succeed(self, account): if account == self.members[0]: self.set_sensitive(False, True) def on_contact_unblock_succeed(self, account): if account == self.members[0]: self.set_sensitive(True) def on_emote(self, emote): '''called when a emote is selected on the emote window''' self.input.append(emote) def on_notify_attention(self): '''called when the nudge button is clicked''' self.session.request_attention(self.cid) message = e3.Message(e3.Message.TYPE_NUDGE, '', None, None) message.body = _('You just sent a nudge!') msg = gui.Message.from_information(self.session.contacts.me, message) self.output.information(self.formatter, msg) self.conv_status.post_process_message(msg) self.play_nudge() def show(self): '''override the show method''' raise NotImplementedError("Method not implemented") def iconify(self): '''override the iconify method''' raise NotImplementedError("Method not implemented") def update_message_waiting(self, is_waiting): """ update the information on the conversation to inform if a message is waiting is_waiting -- boolean value that indicates if a message is waiting """ raise NotImplementedError("Method not implemented") def update_single_information(self, nick, message, account): """ update the information for a conversation with a single user nick -- the nick of the other account (escaped) message -- the message of the other account (escaped) account -- the account """ raise NotImplementedError("Method not implemented") def update_group_information(self): """ update the information for a conversation with multiple users """ raise NotImplementedError("Method not implemented") def set_sensitive(self, is_sensitive, force_sensitive_block_button=False): """ used to make the conversation insensitive while the conversation is still open while the user is disconnected and to set it back to sensitive when the user is reconnected """ raise NotImplementedError("Method not implemented") def set_image_visible(self, is_visible): """ set the visibility of the widget that displays the images of the members is_visible -- boolean that says if the message should be shown or hidden """ raise NotImplementedError("Method not implemented") def set_header_visible(self, is_visible): ''' hide or show the widget according to is_visible is_visible -- boolean that says if the widget should be shown or hidden ''' raise NotImplementedError("Method not implemented") def set_toolbar_visible(self, is_visible): ''' hide or show the widget according to is_visible is_visible -- boolean that says if the widget should be shown or hidden ''' raise NotImplementedError("Method not implemented") def input_grab_focus(self): ''' sets the focus on the input widget ''' raise NotImplementedError("Method not implemented") def on_close(self): '''called when the conversation is closed''' raise NotImplementedError("Method not implemented") def _get_message_waiting(self): '''return True if a message is waiting''' return self._message_waiting def _set_message_waiting(self, value): '''set the value of message waiting, update the gui to reflect the value''' self._message_waiting = value self.update_message_waiting(value) message_waiting = property(fget=_get_message_waiting, fset=_set_message_waiting) def _get_group_chat(self): '''return True if the conversation contains more than one member, false otherwise''' return len(self.members) > 1 is_group_chat = property(fget=_get_group_chat) def _send_typing_notification(self): '''method called to send typing notifications''' self.session.send_typing_notification(self.cid) def output_message(self, message, cedict): '''display current outgoing message into OutputText''' msg = self.conv_status.pre_process_message(self.session.contacts.me, message, False, cedict, self.emcache.path, message.timestamp, message.type, self.cstyle) self.output.send_message(self.formatter, msg) self.conv_status.post_process_message(msg) def _on_send_message(self, text): '''method called when the user press enter on the input text''' cedict = self.emcache.parse() custom_emoticons = gui.base.MarkupParser.get_custom_emotes( text, cedict) self.session.send_message(self.cid, text, self.cstyle, cedict, custom_emoticons) message = e3.Message(e3.Message.TYPE_MESSAGE, text, None, self.cstyle) self.output_message(message, cedict) self.messages.push(text) self.reset_message_offset() self.play_send() self.conv_status.update_status() def input_message(self, message, contact, cedict, cepath): '''display current ingoing message into OutputText''' msg = self.conv_status.pre_process_message(contact, message, True, cedict, cepath, message.timestamp, message.type, message.style) self.output.receive_message(self.formatter, msg) self.conv_status.post_process_message(msg) def on_receive_message(self, message, account, received_custom_emoticons): '''method called when a message arrives to the conversation''' contact = self.session.contacts.safe_get(account) if message.type == e3.Message.TYPE_MESSAGE or \ message.type == e3.Message.TYPE_FLNMSG: if self.session.config.b_override_text_color: message.style.color = \ e3.base.Color.from_hex(self.session.config.override_text_color) user_emcache = self.caches.get_emoticon_cache(account) #XXX: when we send messages from the web iface we get those here, so show them propertly if contact.account == self.session.contacts.me.account: self.output_message(message, None) return self.input_message(message, contact, received_custom_emoticons, user_emcache.path) self.play_type() elif message.type == e3.Message.TYPE_NUDGE: message.body = _('%s just sent you a nudge!') % ( contact.display_name, ) msg = gui.Message.from_information(contact, message) self.output.information(self.formatter, msg) self.conv_status.post_process_message(msg) self.play_nudge() elif message.type == e3.Message.TYPE_INFO: msg = gui.Message.from_information(contact, message) self.output.information(self.formatter, msg) self.conv_status.post_process_message(msg) self.conv_status.update_status() def on_send_message_failed(self, errorCode): '''method called when a message fails to be delivered''' contact = self.session.contacts.me message = e3.Message(e3.Message.TYPE_MESSAGE, '', None, None) message.body = _('Error delivering message') msg = gui.Message.from_information(contact, message) self.output.information(self.formatter, msg) self.conv_status.post_process_message(msg) self.conv_status.update_status() def on_user_typing(self, account): '''method called when a someone is typing''' raise NotImplementedError def _get_icon(self): '''return the icon that represent the current status of the conversation (the status of the contact on a single conversation, a group icon on group chat or a waiting icon) ''' if self.message_waiting: icon = gui.theme.image_theme.new_message elif self.is_group_chat: icon = gui.theme.image_theme.group_chat elif len(self.members) == 1: contact = self.session.contacts.get(self.members[0]) # can be false if we are un a group chat with someone we dont # have and the last contact leaves.. if contact: stat = contact.status else: stat = e3.status.ONLINE icon = gui.theme.image_theme.status_icons.get( stat, e3.status.OFFLINE) else: log.debug('unknown state on Conversation._get_icon') return gui.theme.image_theme.connect return icon icon = property(fget=_get_icon) def _get_text(self): '''return the text that represent the conversation title''' if self.is_group_chat: text = _('Group chat') elif len(self.members) == 1: contact = self.session.contacts.safe_get(self.members[0]) text = contact.display_name else: log.debug('unknown state on Conversation._get_text') text = '(?)' return text text = property(fget=_get_text) def update_data(self): '''update the data on the conversation''' if len(self.members) == 1: self._update_single_information(self.members[0]) elif len(self.members) > 1: self.update_group_information() def update_p2p(self, account, _type, *what): ''' update the p2p data in the conversation (custom emoticons) ''' self.output.update_p2p(account, _type, *what) def on_contact_joined(self, account): '''called when a contact joins the conversation''' if account not in self.members: self.members.append(account) contact = self.session.contacts.safe_get(account) if len(self.members) > 1: message = e3.base.Message(e3.base.Message.TYPE_MESSAGE, \ _('%s has joined the conversation') % (contact.display_name), \ account) msg = gui.Message.from_information(contact, message) self.output.information(self.formatter, msg) self.conv_status.post_process_message(msg) self.update_data() def on_contact_left(self, account): '''called when a contact leaves the conversation''' if len(self.members) > 1 and account in self.members: self.members.remove(account) self.update_data() contact = self.session.contacts.safe_get(account) message = e3.base.Message(e3.base.Message.TYPE_MESSAGE, \ _('%s has left the conversation') % (contact.display_name), \ account) msg = gui.Message.from_information(contact, message) self.output.information(self.formatter, msg) self.conv_status.post_process_message(msg) def on_group_started(self): '''called when a group conversation starts''' self.update_data() def on_group_ended(self): '''called when a group conversation ends''' self.update_data() def _update_single_information(self, account): '''set the data of the conversation to the data of the account''' contact = self.session.contacts.safe_get(account) if contact.media == '': message = MarkupParser.escape(contact.message) else: message = MarkupParser.escape(contact.media) nick = MarkupParser.escape(contact.display_name) self.update_single_information(nick, message, account) def _set_image_visible(self, value): '''hide or show the widget according to value''' self.set_image_visible(value) self._image_visible = value def _get_image_visible(self): '''return the value of image_visible''' return self._image_visible image_visible = property(fget=_get_image_visible, fset=_set_image_visible) def _set_header_visible(self, value): '''hide or show the widget according to value''' self.set_header_visible(value) self._header_visible = value def _get_header_visible(self): '''return the value of _header_visible''' return self._header_visible header_visible = property(fget=_get_header_visible, fset=_set_header_visible) def _set_toolbar_visible(self, value): '''hide or show the widget according to value''' self.set_toolbar_visible(value) self._toolbar_visible = value def _get_toolbar_visible(self): '''return the value of image_visible''' return self._toolbar_visible toolbar_visible = property(fget=_get_toolbar_visible, fset=_set_toolbar_visible) def play_nudge(self): """ play the nudge sound """ if self.session.config.b_play_nudge: self.soundPlayer.play(gui.theme.sound_theme.sound_nudge) def play_send(self): """ play the send sound """ if self.session.config.b_play_send: self.soundPlayer.play(gui.theme.sound_theme.sound_send) def play_type(self): """ play the receive sound """ if self.session.config.b_play_type and (self.message_waiting or not \ self.session.config.b_mute_sounds_when_focussed): self.soundPlayer.play(gui.theme.sound_theme.sound_type) def cycle_history(self, change=-1): """ return one of the last N messages sent, the one returned is the one pointed by message_offset, every time you call this function it will go to the previous one, you can reset it using reset_message_offset. change is the direction of cycling, 1 will go forward -1 will go backwards if no message in the buffer return an empty string if there is message before cycling, it will be stored till the message sent """ if change < 0 and self.message_offset == 0: self.message_input = self.input.text self.message_offset += change if abs(self.message_offset) + 1 > len(self.messages): self.message_offset = 1 - len(self.messages) if self.message_offset > 0: self.reset_message_offset() try: if self.message_offset == 0: self.input.text = self.message_input else: self.input.text = self.messages.peak(self.message_offset) except IndexError: pass def reset_message_offset(self): self.message_offset = 0 def _member_to_contact(self, member): return self.session.contacts.safe_get(member) def steal_emoticon(self, uri): """ receives the path or the uri for the emoticon to be added """ raise NotImplementedError("Method not implemented")
class Conversation(object): '''a widget that contains all the components inside''' def __init__(self, session, cid, update_window, members=None): '''constructor''' self.update_window = update_window self.session = session self.caches = e3.cache.CacheManager(self.session.config_dir.base_dir) self.emcache = self.caches.get_emoticon_cache(self.session.account.account) self.cid = float(cid) self.formatter = e3.common.MessageFormatter(session.contacts.me) self.first = True self._header_visible = True self._image_visible = True self._toolbar_visible = True self._message_waiting = True buffer_size = session.config.get_or_set("i_msg_history_size", 5) self.messages = RingBuffer(max=buffer_size) self.message_offset = 0 if members is None: self.members = [] else: self.members = members self._style = None # the base class should override this attributes self.info = None self.input = None self.output = None def _get_style(self): '''return the value of style''' return self._style def _set_style(self, style): '''set the value of style and update the style on input''' self._style = style self.session.config.font = style.font self.session.config.i_font_size = style.size self.session.config.b_font_bold = style.bold self.session.config.b_font_italic = style.italic self.session.config.b_font_underline = style.underline self.session.config.b_font_strike = style.strike self.session.config.font_color = '#' + style.color.to_hex() self.input.update_style(style) cstyle = property(fget=_get_style, fset=_set_style) def _load_style(self): '''load the default style from the configuration''' font = self.session.config.get_or_set("font", "Sans") font_color = self.session.config.get_or_set("font_color", "#000000") font_size = self.session.config.get_or_set("i_font_size", 10) font_bold = self.session.config.get_or_set("b_font_bold", False) font_italic = self.session.config.get_or_set("b_font_italic", False) font_underline = self.session.config.get_or_set("b_font_underline", False) font_strike = self.session.config.get_or_set("b_font_strike", False) if self.session.config.i_font_size < 6 or \ self.session.config.i_font_size > 32: font_size = self.session.config.i_font_size = 10 try: color = e3.Color.from_hex(font_color) except ValueError: font_color = self.session.config.font_color = '#000000' color = e3.Color.from_hex(font_color) self.cstyle = e3.Style(font, color, font_bold, font_italic, font_underline, font_strike, font_size) def get_preview(self, completepath): return None def on_font_selected(self, style): '''called when a new font is selected''' self.cstyle = style def on_color_selected(self, color): '''called when a new font is selected''' self.cstyle.color = color self.session.config.font_color = '#' + color.to_hex() self.input.update_style(self.cstyle) def on_style_selected(self, style): '''called when a new font is selected''' self.cstyle = style def on_invite(self, account): '''called when a contact is selected to be invited''' self.session.conversation_invite(self.cid, account) def on_filetransfer_invite(self, filename, completepath): '''called when a filetransfer is issued''' self.session.filetransfer_invite(self.cid, self.members[0], filename, completepath, self.get_preview(completepath)) def on_video_call(self): '''called when the user is requesting a video-only call''' raise NotImplementedError def on_voice_call(self): '''called when the user is requesting an audio-only call''' raise NotImplementedError def on_av_call(self): '''called when the user is requesting an audio-video call''' raise NotImplementedError def on_clean(self): '''called when the clean button is clicked''' self.output.clear() def on_block_user(self): '''blocks the first user of the conversation''' account = self.members[0] contact = self.session.contacts.contacts[account] if contact.blocked: self.session.unblock(account) else: self.session.block(account) def on_emote(self, emote): '''called when a emote is selected on the emote window''' self.input.append(emote) def on_notify_attention(self): '''called when the nudge button is clicked''' self.session.request_attention(self.cid) message = e3.Message(e3.Message.TYPE_NUDGE, '', None, None) self.output.send_message(self.formatter, self.session.contacts.me, message, {}, '', self.first) self.play_nudge() def show(self): '''override the show method''' raise NotImplementedError("Method not implemented") def iconify(self): '''override the iconify method''' raise NotImplementedError("Method not implemented") def update_message_waiting(self, is_waiting): """ update the information on the conversation to inform if a message is waiting is_waiting -- boolean value that indicates if a message is waiting """ raise NotImplementedError("Method not implemented") def update_single_information(self, nick, message, account): """ update the information for a conversation with a single user nick -- the nick of the other account (escaped) message -- the message of the other account (escaped) account -- the account """ raise NotImplementedError("Method not implemented") def update_group_information(self): """ update the information for a conversation with multiple users """ raise NotImplementedError("Method not implemented") def set_image_visible(self, is_visible): """ set the visibility of the widget that displays the images of the members is_visible -- boolean that says if the message should be shown or hidden """ raise NotImplementedError("Method not implemented") def set_header_visible(self, is_visible): ''' hide or show the widget according to is_visible is_visible -- boolean that says if the widget should be shown or hidden ''' raise NotImplementedError("Method not implemented") def set_toolbar_visible(self, is_visible): ''' hide or show the widget according to is_visible is_visible -- boolean that says if the widget should be shown or hidden ''' raise NotImplementedError("Method not implemented") def input_grab_focus(self): ''' sets the focus on the input widget ''' raise NotImplementedError("Method not implemented") def on_close(self): '''called when the conversation is closed''' raise NotImplementedError("Method not implemented") def _get_message_waiting(self): '''return True if a message is waiting''' return self._message_waiting def _set_message_waiting(self, value): '''set the value of message waiting, update the gui to reflect the value''' self._message_waiting = value self.update_message_waiting(value) message_waiting = property(fget=_get_message_waiting, fset=_set_message_waiting) def _get_group_chat(self): '''return True if the conversation contains more than one member, false otherwise''' return len(self.members) > 1 group_chat = property(fget=_get_group_chat) def _on_send_message(self, text): '''method called when the user press enter on the input text''' custom_emoticons = gui.base.MarkupParser.get_custom_emotes(text, self.emcache.parse()) self.session.send_message(self.cid, text, self.cstyle, self.emcache.parse(), custom_emoticons) message = e3.Message(e3.Message.TYPE_MESSAGE, text, None, self.cstyle) self.output.send_message(self.formatter, self.session.contacts.me, message, self.emcache.parse(), self.emcache.path, self.first) self.messages.push(text) self.play_send() self.first = False def on_receive_message(self, message, account, received_custom_emoticons): '''method called when a message arrives to the conversation''' contact = self.session.contacts.get(account) if contact is None: contact = e3.Contact(account) if message.type == e3.Message.TYPE_MESSAGE or message.type == e3.Message.TYPE_FLNMSG: if self.session.config.b_override_text_color: message.style.color = e3.base.Color.from_hex(self.session.config.override_text_color) user_emcache = self.caches.get_emoticon_cache(account) self.output.receive_message(self.formatter, contact, message, received_custom_emoticons, user_emcache.path, self.first) self.play_type() elif message.type == e3.Message.TYPE_NUDGE: self.output.information(self.formatter, contact, _('%s just sent you a nudge!') % (contact.display_name,)) self.play_nudge() self.first = False def on_send_message_failed(self, errorCode): '''method called when a message fails to be delivered''' contact = self.session.contacts.me self.output.information(self.formatter, contact, \ _('Error delivering message')) self.first = False def on_user_typing(self, account): '''method called when a someone is typing''' raise NotImplementedError def _get_icon(self): '''return the icon that represent the current status of the conversation (the status of the contact on a single conversation, a group icon on group chat or a waiting icon) ''' if self.message_waiting: icon = gui.theme.new_message elif self.group_chat: icon = gui.theme.group_chat elif len(self.members) == 1: contact = self.session.contacts.get(self.members[0]) # can be false if we are un a group chat with someone we dont # have and the last contact leaves.. if contact: stat = contact.status else: stat = e3.status.ONLINE icon = gui.theme.status_icons.get(stat, e3.status.OFFLINE) else: log.debug('unknown state on Conversation._get_icon') return gui.theme.connect return icon icon = property(fget=_get_icon) def _get_text(self): '''return the text that represent the conversation title''' if self.group_chat: text = _('Group chat') elif len(self.members) == 1: contact = self.session.contacts.get(self.members[0]) # can be false if we are un a group chat with someone we dont # have and the last contact leaves.. if contact: text = contact.display_name else: text = self.members[0] else: log.debug('unknown state on Conversation._get_text') text = '(?)' return text text = property(fget=_get_text) def update_data(self): '''update the data on the conversation''' if len(self.members) == 1: self._update_single_information(self.members[0]) elif len(self.members) > 1: self.update_group_information() def update_p2p(self, account, _type, *what): ''' update the p2p data in the conversation (custom emoticons) ''' self.output.update_p2p(account, _type, *what) def on_contact_joined(self, account): '''called when a contact joins the conversation''' if account not in self.members: self.members.append(account) self.update_data() def on_contact_left(self, account): '''called when a contact lefts the conversation''' if account in self.members and len(self.members) > 1: self.members.remove(account) self.update_data() def on_group_started(self): '''called when a group conversation starts''' self.update_data() def on_group_ended(self): '''called when a group conversation ends''' self.update_data() def _update_single_information(self, account): '''set the data of the conversation to the data of the account''' contact = self.session.contacts.get(account) if contact: message = MarkupParser.escape(contact.message) nick = MarkupParser.escape(contact.display_name) else: message = '' nick = account self.update_single_information(nick, message, account) def _set_image_visible(self, value): '''hide or show the widget according to value''' self.set_image_visible(value) if value: self.info.show() else: self.info.hide() self._image_visible = value def _get_image_visible(self): '''return the value of image_visible''' return self._image_visible image_visible = property(fget=_get_image_visible, fset=_set_image_visible) def _set_header_visible(self, value): '''hide or show the widget according to value''' self.set_header_visible(value) self._header_visible = value def _get_header_visible(self): '''return the value of image_visible''' return self._header_visible header_visible = property(fget=_get_header_visible, fset=_set_header_visible) def _set_toolbar_visible(self, value): '''hide or show the widget according to value''' self.set_toolbar_visible(value) self._toolbar_visible = value def _get_toolbar_visible(self): '''return the value of image_visible''' return self._toolbar_visible toolbar_visible = property(fget=_get_toolbar_visible, fset=_set_toolbar_visible) def play_nudge(self): """ play the nudge sound """ if self.session.config.b_play_nudge: gui.play(self.session, gui.theme.sound_nudge) def play_send(self): """ play the send sound """ if self.session.config.b_play_send: gui.play(self.session, gui.theme.sound_send) def play_type(self): """ play the receive sound """ if self.session.config.b_play_type and self.message_waiting: gui.play(self.session, gui.theme.sound_type) def cycle_history(self, change=-1): """ return one of the last N messages sent, the one returned is the one pointed by message_offset, every time you call this function it will go to the previous one, you can reset it using reset_message_offset. change is the direction of cycling, 1 will go forward -1 will go backwards if no message in the buffer return an empty string """ self.message_offset += change try: self.input.text = self.messages.peak(self.message_offset) except IndexError: pass def reset_message_offset(self): self.message_offset = 0 def _member_to_contact(self,member): return self.session.contacts.contacts[member]
class Conversation(object): '''a widget that contains all the components inside''' def __init__(self, session, cid, update_window, members=None): '''constructor''' self.update_window = update_window self.session = session self.caches = e3.cache.CacheManager(self.session.config_dir.base_dir) self.emcache = self.caches.get_emoticon_cache( self.session.account.account) self.cid = float(cid) self.formatter = e3.common.MessageFormatter(session.contacts.me) self.first = True self._header_visible = True self._image_visible = True self._toolbar_visible = True self._message_waiting = True buffer_size = session.config.get_or_set("i_msg_history_size", 5) self.messages = RingBuffer(max=buffer_size) self.message_offset = 0 if members is None: self.members = [] else: self.members = members self._style = None # the base class should override this attributes self.info = None self.input = None self.output = None def _get_style(self): '''return the value of style''' return self._style def _set_style(self, style): '''set the value of style and update the style on input''' self._style = style self.session.config.font = style.font self.session.config.i_font_size = style.size self.session.config.b_font_bold = style.bold self.session.config.b_font_italic = style.italic self.session.config.b_font_underline = style.underline self.session.config.b_font_strike = style.strike self.session.config.font_color = '#' + style.color.to_hex() self.input.update_style(style) cstyle = property(fget=_get_style, fset=_set_style) def _load_style(self): '''load the default style from the configuration''' font = self.session.config.get_or_set("font", "Sans") font_color = self.session.config.get_or_set("font_color", "#000000") font_size = self.session.config.get_or_set("i_font_size", 10) font_bold = self.session.config.get_or_set("b_font_bold", False) font_italic = self.session.config.get_or_set("b_font_italic", False) font_underline = self.session.config.get_or_set( "b_font_underline", False) font_strike = self.session.config.get_or_set("b_font_strike", False) if self.session.config.i_font_size < 6 or \ self.session.config.i_font_size > 32: font_size = self.session.config.i_font_size = 10 try: color = e3.Color.from_hex(font_color) except ValueError: font_color = self.session.config.font_color = '#000000' color = e3.Color.from_hex(font_color) self.cstyle = e3.Style(font, color, font_bold, font_italic, font_underline, font_strike, font_size) def get_preview(self, completepath): return None def on_font_selected(self, style): '''called when a new font is selected''' self.cstyle = style def on_color_selected(self, color): '''called when a new font is selected''' self.cstyle.color = color self.session.config.font_color = '#' + color.to_hex() self.input.update_style(self.cstyle) def on_style_selected(self, style): '''called when a new font is selected''' self.cstyle = style def on_invite(self, account): '''called when a contact is selected to be invited''' self.session.conversation_invite(self.cid, account) def on_filetransfer_invite(self, filename, completepath): '''called when a filetransfer is issued''' self.session.filetransfer_invite(self.cid, self.members[0], filename, completepath, self.get_preview(completepath)) def on_video_call(self): '''called when the user is requesting a video-only call''' raise NotImplementedError def on_voice_call(self): '''called when the user is requesting an audio-only call''' raise NotImplementedError def on_av_call(self): '''called when the user is requesting an audio-video call''' raise NotImplementedError def on_clean(self): '''called when the clean button is clicked''' self.output.clear() def on_block_user(self): '''blocks the first user of the conversation''' account = self.members[0] contact = self.session.contacts.contacts[account] if contact.blocked: self.session.unblock(account) else: self.session.block(account) def on_emote(self, emote): '''called when a emote is selected on the emote window''' self.input.append(emote) def on_notify_attention(self): '''called when the nudge button is clicked''' self.session.request_attention(self.cid) message = e3.Message(e3.Message.TYPE_NUDGE, '', None, None) self.output.send_message(self.formatter, self.session.contacts.me, message, {}, '', self.first) self.play_nudge() def show(self): '''override the show method''' raise NotImplementedError("Method not implemented") def iconify(self): '''override the iconify method''' raise NotImplementedError("Method not implemented") def update_message_waiting(self, is_waiting): """ update the information on the conversation to inform if a message is waiting is_waiting -- boolean value that indicates if a message is waiting """ raise NotImplementedError("Method not implemented") def update_single_information(self, nick, message, account): """ update the information for a conversation with a single user nick -- the nick of the other account (escaped) message -- the message of the other account (escaped) account -- the account """ raise NotImplementedError("Method not implemented") def update_group_information(self): """ update the information for a conversation with multiple users """ raise NotImplementedError("Method not implemented") def set_image_visible(self, is_visible): """ set the visibility of the widget that displays the images of the members is_visible -- boolean that says if the message should be shown or hidden """ raise NotImplementedError("Method not implemented") def set_header_visible(self, is_visible): ''' hide or show the widget according to is_visible is_visible -- boolean that says if the widget should be shown or hidden ''' raise NotImplementedError("Method not implemented") def set_toolbar_visible(self, is_visible): ''' hide or show the widget according to is_visible is_visible -- boolean that says if the widget should be shown or hidden ''' raise NotImplementedError("Method not implemented") def input_grab_focus(self): ''' sets the focus on the input widget ''' raise NotImplementedError("Method not implemented") def on_close(self): '''called when the conversation is closed''' raise NotImplementedError("Method not implemented") def _get_message_waiting(self): '''return True if a message is waiting''' return self._message_waiting def _set_message_waiting(self, value): '''set the value of message waiting, update the gui to reflect the value''' self._message_waiting = value self.update_message_waiting(value) message_waiting = property(fget=_get_message_waiting, fset=_set_message_waiting) def _get_group_chat(self): '''return True if the conversation contains more than one member, false otherwise''' return len(self.members) > 1 group_chat = property(fget=_get_group_chat) def _on_send_message(self, text): '''method called when the user press enter on the input text''' custom_emoticons = gui.base.MarkupParser.get_custom_emotes( text, self.emcache.parse()) self.session.send_message(self.cid, text, self.cstyle, self.emcache.parse(), custom_emoticons) message = e3.Message(e3.Message.TYPE_MESSAGE, text, None, self.cstyle) self.output.send_message(self.formatter, self.session.contacts.me, message, self.emcache.parse(), self.emcache.path, self.first) self.messages.push(text) self.play_send() self.first = False def on_receive_message(self, message, account, received_custom_emoticons): '''method called when a message arrives to the conversation''' contact = self.session.contacts.get(account) if contact is None: contact = e3.Contact(account) if message.type == e3.Message.TYPE_MESSAGE or message.type == e3.Message.TYPE_FLNMSG: if self.session.config.b_override_text_color: message.style.color = e3.base.Color.from_hex( self.session.config.override_text_color) user_emcache = self.caches.get_emoticon_cache(account) self.output.receive_message(self.formatter, contact, message, received_custom_emoticons, user_emcache.path, self.first) self.play_type() elif message.type == e3.Message.TYPE_NUDGE: self.output.information( self.formatter, contact, _('%s just sent you a nudge!') % (contact.display_name, )) self.play_nudge() self.first = False def on_send_message_failed(self, errorCode): '''method called when a message fails to be delivered''' contact = self.session.contacts.me self.output.information(self.formatter, contact, \ _('Error delivering message')) self.first = False def on_user_typing(self, account): '''method called when a someone is typing''' raise NotImplementedError def _get_icon(self): '''return the icon that represent the current status of the conversation (the status of the contact on a single conversation, a group icon on group chat or a waiting icon) ''' if self.message_waiting: icon = gui.theme.new_message elif self.group_chat: icon = gui.theme.group_chat elif len(self.members) == 1: contact = self.session.contacts.get(self.members[0]) # can be false if we are un a group chat with someone we dont # have and the last contact leaves.. if contact: stat = contact.status else: stat = e3.status.ONLINE icon = gui.theme.status_icons.get(stat, e3.status.OFFLINE) else: log.debug('unknown state on Conversation._get_icon') return gui.theme.connect return icon icon = property(fget=_get_icon) def _get_text(self): '''return the text that represent the conversation title''' if self.group_chat: text = _('Group chat') elif len(self.members) == 1: contact = self.session.contacts.get(self.members[0]) # can be false if we are un a group chat with someone we dont # have and the last contact leaves.. if contact: text = contact.display_name else: text = self.members[0] else: log.debug('unknown state on Conversation._get_text') text = '(?)' return text text = property(fget=_get_text) def update_data(self): '''update the data on the conversation''' if len(self.members) == 1: self._update_single_information(self.members[0]) elif len(self.members) > 1: self.update_group_information() def update_p2p(self, account, _type, *what): ''' update the p2p data in the conversation (custom emoticons) ''' self.output.update_p2p(account, _type, *what) def on_contact_joined(self, account): '''called when a contact joins the conversation''' if account not in self.members: self.members.append(account) self.update_data() def on_contact_left(self, account): '''called when a contact lefts the conversation''' if account in self.members and len(self.members) > 1: self.members.remove(account) self.update_data() def on_group_started(self): '''called when a group conversation starts''' self.update_data() def on_group_ended(self): '''called when a group conversation ends''' self.update_data() def _update_single_information(self, account): '''set the data of the conversation to the data of the account''' contact = self.session.contacts.get(account) if contact: message = MarkupParser.escape(contact.message) nick = MarkupParser.escape(contact.display_name) else: message = '' nick = account self.update_single_information(nick, message, account) def _set_image_visible(self, value): '''hide or show the widget according to value''' self.set_image_visible(value) if value: self.info.show() else: self.info.hide() self._image_visible = value def _get_image_visible(self): '''return the value of image_visible''' return self._image_visible image_visible = property(fget=_get_image_visible, fset=_set_image_visible) def _set_header_visible(self, value): '''hide or show the widget according to value''' self.set_header_visible(value) self._header_visible = value def _get_header_visible(self): '''return the value of image_visible''' return self._header_visible header_visible = property(fget=_get_header_visible, fset=_set_header_visible) def _set_toolbar_visible(self, value): '''hide or show the widget according to value''' self.set_toolbar_visible(value) self._toolbar_visible = value def _get_toolbar_visible(self): '''return the value of image_visible''' return self._toolbar_visible toolbar_visible = property(fget=_get_toolbar_visible, fset=_set_toolbar_visible) def play_nudge(self): """ play the nudge sound """ if self.session.config.b_play_nudge: gui.play(self.session, gui.theme.sound_nudge) def play_send(self): """ play the send sound """ if self.session.config.b_play_send: gui.play(self.session, gui.theme.sound_send) def play_type(self): """ play the receive sound """ if self.session.config.b_play_type and self.message_waiting: gui.play(self.session, gui.theme.sound_type) def cycle_history(self, change=-1): """ return one of the last N messages sent, the one returned is the one pointed by message_offset, every time you call this function it will go to the previous one, you can reset it using reset_message_offset. change is the direction of cycling, 1 will go forward -1 will go backwards if no message in the buffer return an empty string """ self.message_offset += change try: self.input.text = self.messages.peak(self.message_offset) except IndexError: pass def reset_message_offset(self): self.message_offset = 0 def _member_to_contact(self, member): return self.session.contacts.contacts[member]