summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core.py156
-rw-r--r--src/room.py132
-rw-r--r--src/tabs.py242
-rw-r--r--src/text_buffer.py7
-rw-r--r--src/windows.py10
5 files changed, 241 insertions, 306 deletions
diff --git a/src/core.py b/src/core.py
index ec821cbd..35cc6951 100644
--- a/src/core.py
+++ b/src/core.py
@@ -40,7 +40,6 @@ from data_forms import DataFormsTab
from config import config, options
from logger import logger
from user import User
-from room import Room
from roster import Roster, RosterGroup, roster
from contact import Contact, Resource
from text_buffer import TextBuffer
@@ -335,10 +334,10 @@ class Core(object):
nick = message['mucnick']
room_from = message.getMucroom()
tab = self.get_tab_by_name(room_from, tabs.MucTab)
- if tab and tab.get_room() and tab.get_room().get_user_by_name(nick):
- tab.get_room().get_user_by_name(nick).chatstate = state
+ if tab and tab.get_user_by_name(nick):
+ tab.get_user_by_name(nick).chatstate = state
if tab == self.current_tab():
- tab.user_win.refresh(tab._room.users)
+ tab.user_win.refresh(tab.users)
tab.input.refresh()
self.doupdate()
@@ -357,7 +356,6 @@ class Core(object):
logger.log_roster_change(jid.bare, 'got offline')
if not contact:
return
- log.debug('on_got_offline: %s' % presence)
resource = contact.get_resource_by_fulljid(jid.full)
if not resource:
return
@@ -403,7 +401,7 @@ class Core(object):
"""
tab = self.get_tab_by_name(jid, tabs.ConversationTab)
if tab:
- self.add_message_to_text_buffer(tab.get_room(), msg)
+ self.add_message_to_text_buffer(tab._text_buffer, msg)
def on_failed_connection(self):
"""
@@ -417,7 +415,7 @@ class Core(object):
"""
for tab in self.tabs:
if isinstance(tab, tabs.MucTab):
- tab.get_room().disconnect()
+ tab.disconnect()
self.information(_("Disconnected from server."))
def on_failed_auth(self, event):
@@ -518,7 +516,7 @@ class Core(object):
def on_user_changed_status_in_private(self, jid, msg):
tab = self.get_tab_by_name(jid)
if tab: # display the message in private
- tab.get_room().add_message(msg)
+ tab.add_message(msg)
def on_message(self, message):
"""
@@ -544,16 +542,16 @@ class Core(object):
jid = message['from']
nick_from = jid.resource
room_from = jid.bare
- room = self.get_room_by_name(jid.full) # get the tab with the private conversation
- if not room: # It's the first message we receive: create the tab
- room = self.open_private_window(room_from, nick_from, False)
- if not room:
+ tab = self.get_tab_by_name(jid.full, tabs.PrivateTab) # get the tab with the private conversation
+ if not tab: # It's the first message we receive: create the tab
+ tab = self.open_private_window(room_from, nick_from, False)
+ if not tab:
return
body = xhtml.get_body_from_message_stanza(message)
if not body:
return
- room.add_message(body, time=None, nickname=nick_from,
- forced_user=self.get_room_by_name(room_from).get_user_by_name(nick_from))
+ tab.add_message(body, time=None, nickname=nick_from,
+ forced_user=self.get_tab_by_name(room_from, tabs.MucTab).get_user_by_name(nick_from))
conversation = self.get_tab_by_name(jid.full, tabs.PrivateTab)
if conversation and conversation.remote_wants_chatstates is None:
if message['chat_state']:
@@ -607,7 +605,7 @@ class Core(object):
remote_nick = roster.get_contact_by_jid(jid.bare).get_name() or jid.user
else:
remote_nick = jid.user
- conversation.get_room().add_message(body, nickname=remote_nick, nick_color=get_theme().COLOR_REMOTE_USER)
+ conversation._text_buffer.add_message(body, nickname=remote_nick, nick_color=get_theme().COLOR_REMOTE_USER)
if conversation.remote_wants_chatstates is None:
if message['chat_state']:
conversation.remote_wants_chatstates = True
@@ -767,7 +765,7 @@ class Core(object):
for tab in self.tabs:
if isinstance(tab, tabs.ConversationTab):
if tab.get_name() == jid:
- return tab.get_room()
+ return tab
return None
def get_tab_by_name(self, name, typ=None):
@@ -788,16 +786,6 @@ class Core(object):
return tab
return None
- def get_room_by_name(self, name):
- """
- returns the room that has this name
- """
- for tab in self.tabs:
- if (isinstance(tab, tabs.MucTab) or
- isinstance(tab, tabs.PrivateTab)) and tab.get_name() == name:
- return tab.get_room()
- return None
-
def init_curses(self, stdscr):
"""
ncurses initialization
@@ -859,8 +847,7 @@ class Core(object):
"""
Open a new tab.MucTab containing a muc Room, using the specified nick
"""
- r = Room(room, nick)
- new_tab = tabs.MucTab(r)
+ new_tab = tabs.MucTab(room, nick)
self.add_tab(new_tab, focus)
self.refresh_window()
@@ -947,20 +934,20 @@ class Core(object):
def room_error(self, error, room_name):
"""
- Display the error on the room window
+ Display the error in the tab
"""
- room = self.get_room_by_name(room_name)
+ tab = self.get_tab_by_name(room_name)
error_message = self.get_error_message_from_error_stanza(error)
- self.add_message_to_text_buffer(room, error_message)
+ self.add_message_to_text_buffer(tab._text_buffer, error_message)
code = error['error']['code']
if code == '401':
msg = _('To provide a password in order to join the room, type "/join / password" (replace "password" by the real password)')
- self.add_message_to_text_buffer(room, msg)
+ self.add_message_to_text_buffer(tab._text_buffer, msg)
if code == '409':
if config.get('alternative_nickname', '') != '':
- self.command_join('%s/%s'% (room.name, room.own_nick+config.get('alternative_nickname', '')))
+ self.command_join('%s/%s'% (tab.name, tab.own_nick+config.get('alternative_nickname', '')))
else:
- self.add_message_to_text_buffer(room, _('You can join the room with an other nick, by typing "/join /other_nick"'))
+ self.add_message_to_text_buffer(tab._text_buffer, _('You can join the room with an other nick, by typing "/join /other_nick"'))
self.refresh_window()
def open_conversation_window(self, jid, focus=True):
@@ -986,21 +973,18 @@ class Core(object):
if isinstance(tab, tabs.PrivateTab):
if tab.get_name() == complete_jid:
self.command_win('%s' % tab.nb)
- return tab.get_room()
+ return tab
# create the new tab
- room = self.get_room_by_name(room_name)
- if not room:
+ tab = self.get_tab_by_name(room_name, tabs.MucTab)
+ if not tab:
return None
- own_nick = room.own_nick
- r = Room(complete_jid, own_nick) # PrivateRoom here
- new_tab = tabs.PrivateTab(r)
+ new_tab = tabs.PrivateTab(complete_jid, tab.own_nick)
if not focus:
new_tab.state = "private"
# insert it in the tabs
self.add_tab(new_tab, focus)
- # self.window.new_room(r)
self.refresh_window()
- return r
+ return new_tab
def on_groupchat_subject(self, message):
"""
@@ -1008,15 +992,15 @@ class Core(object):
"""
nick_from = message['mucnick']
room_from = message.getMucroom()
- room = self.get_room_by_name(room_from)
+ tab = self.get_tab_by_name(room_from, tabs.MucTab)
subject = message['subject']
- if not subject or not room:
+ if not subject or not tab:
return
if nick_from:
- self.add_message_to_text_buffer(room, _("%(nick)s set the subject to: %(subject)s") % {'nick':nick_from, 'subject':subject}, time=None)
+ self.add_message_to_text_buffer(tab._text_buffer, _("%(nick)s set the subject to: %(subject)s") % {'nick':nick_from, 'subject':subject}, time=None)
else:
- self.add_message_to_text_buffer(room, _("The subject is: %(subject)s") % {'subject':subject}, time=None)
- room.topic = subject
+ self.add_message_to_text_buffer(tab._text_buffer, _("The subject is: %(subject)s") % {'subject':subject}, time=None)
+ tab.topic = subject
if self.get_tab_by_name(room_from, tabs.MucTab) is self.current_tab():
self.refresh_window()
@@ -1044,34 +1028,33 @@ class Core(object):
room_from = message.getMucroom()
if message['type'] == 'error': # Check if it's an error
return self.room_error(message, room_from)
- room = self.get_room_by_name(room_from)
tab = self.get_tab_by_name(room_from, tabs.MucTab)
- if tab and tab.get_room() and tab.get_room().get_user_by_name(nick_from) and\
- tab.get_room().get_user_by_name(nick_from) in tab.ignores:
- return
- if not room:
+ if not tab:
self.information(_("message received for a non-existing room: %s") % (room_from))
return
+ if tab.get_user_by_name(nick_from) and\
+ tab.get_user_by_name(nick_from) in tab.ignores:
+ return
body = xhtml.get_body_from_message_stanza(message)
if body:
date = date if delayed == True else None
- self.add_message_to_text_buffer(room, body, date, nick_from, history=True if date else False)
+ tab.add_message(body, date, nick_from, history=True if date else False)
if tab is self.current_tab():
- tab.text_win.refresh(tab._room)
- tab.info_header.refresh(tab._room, tab.text_win)
+ tab.text_win.refresh()
+ tab.info_header.refresh(tab, tab.text_win)
self.refresh_tab_win()
if 'message' in config.get('beep_on', 'highlight private').split():
curses.beep()
- def add_message_to_text_buffer(self, room, txt, time=None, nickname=None, history=None):
+ def add_message_to_text_buffer(self, buff, txt, time=None, nickname=None, history=None):
"""
Add the message to the room if possible, else, add it to the Info window
(in the Info tab of the info window in the RosterTab)
"""
- if not room:
+ if not buff:
self.information('Trying to add a message in no room: %s' % txt, 'Error')
else:
- room.add_message(txt, time, nickname, history=history)
+ buff.add_message(txt, time, nickname, history=history)
def command_help(self, arg):
"""
@@ -1121,13 +1104,13 @@ class Core(object):
pres['type'] = show
pres.send()
current = self.current_tab()
- if isinstance(current, tabs.MucTab) and current.get_room().joined and show in ('away', 'xa'):
+ if isinstance(current, tabs.MucTab) and current.joined and show in ('away', 'xa'):
current.send_chat_state('inactive')
for tab in self.tabs:
- if isinstance(tab, tabs.MucTab) and tab.get_room().joined:
- muc.change_show(self.xmpp, tab.get_room().name, tab.get_room().own_nick, show, msg)
+ if isinstance(tab, tabs.MucTab) and tab.joined:
+ muc.change_show(self.xmpp, tab.name, tab.own_nick, show, msg)
self.set_status(show, msg)
- if isinstance(current, tabs.MucTab) and current.get_room().joined and show not in ('away', 'xa'):
+ if isinstance(current, tabs.MucTab) and current.joined and show not in ('away', 'xa'):
current.send_chat_state('active')
def completion_status(self, the_input):
@@ -1281,11 +1264,11 @@ class Core(object):
args = common.shell_split(arg)
password = None
if len(args) == 0:
- t = self.current_tab()
- if not isinstance(t, tabs.MucTab) and not isinstance(t, tabs.PrivateTab):
+ tab = self.current_tab()
+ if not isinstance(tab, tabs.MucTab) and not isinstance(tab, tabs.PrivateTab):
return
- room = JID(t.get_name()).bare
- nick = t.get_room().own_nick
+ room = JID(tab.get_name()).bare
+ nick = tab.own_nick
else:
info = JID(args[0])
if info.resource == '':
@@ -1296,12 +1279,12 @@ class Core(object):
else:
nick = info.resource
if info.bare == '': # happens with /join /nickname, which is OK
- t = self.current_tab()
- if not isinstance(t, tabs.MucTab):
+ tab = self.current_tab()
+ if not isinstance(tab, tabs.MucTab):
return
- room = t.get_name()
+ room = tab.get_name()
if nick == '':
- nick = t.get_room().own_nick
+ nick = tab.own_nick
else:
room = info.bare
if room.find('@') == -1: # no server is provided, like "/join hello"
@@ -1314,25 +1297,25 @@ class Core(object):
self.information(_("You didn't specify a server for the room you want to join"), 'Error')
return
room = room.lower()
- r = self.get_room_by_name(room)
+ tab = self.get_tab_by_name(room, tabs.MucTab)
if len(args) == 2: # a password is provided
password = args[1]
- if r and r.joined: # if we are already in the room
- self.focus_tab_named(r.name)
+ if tab and tab.joined: # if we are already in the room
+ self.focus_tab_named(tab.name)
return
if room.startswith('@'):
room = room[1:]
current_status = self.get_status()
- if r and not r.joined:
+ if tab and not tab.joined:
muc.join_groupchat(self.xmpp, room, nick, password,
histo_length, current_status.message, current_status.show)
- if not r: # if the room window exists, we don't recreate it.
+ if not tab:
self.open_new_room(room, nick)
muc.join_groupchat(self.xmpp, room, nick, password,
histo_length, current_status.message, current_status.show)
else:
- r.own_nick = nick
- r.users = []
+ tab.own_nick = nick
+ tab.users = []
self.enable_private_tabs(room)
def get_bookmark_nickname(self, room_name):
@@ -1356,10 +1339,10 @@ class Core(object):
if len(args) == 0 and not isinstance(self.current_tab(), tabs.MucTab):
return
if len(args) == 0:
- room = self.current_tab().get_room()
- roomname = self.current_tab().get_name()
- if room.joined:
- nick = room.own_nick
+ tab = self.current_tab()
+ roomname = tab.get_name()
+ if tab.joined:
+ nick = tab.own_nick
else:
info = JID(args[0])
if info.resource != '':
@@ -1459,9 +1442,9 @@ class Core(object):
return
for tab in self.tabs:
if isinstance(tab, tabs.MucTab) and JID(tab.get_name()).domain == domain:
- if tab.get_room().joined:
- muc.leave_groupchat(tab.core.xmpp, tab.get_name(), tab.get_room().own_nick, message)
- tab.get_room().joined = False
+ if tab.joined:
+ muc.leave_groupchat(tab.core.xmpp, tab.get_name(), tab.own_nick, message)
+ tab.joined = False
self.command_join(tab.get_name())
def command_bind(self, arg):
@@ -1518,7 +1501,7 @@ class Core(object):
self.pop_information_win_up(nb_lines, popup_time)
else:
if self.information_win_size != 0:
- self.information_win.refresh(self.information_buffer)
+ self.information_win.refresh()
self.current_tab().input.refresh()
def disconnect(self, msg=None, reconnect=False):
@@ -1528,7 +1511,7 @@ class Core(object):
"""
for tab in self.tabs:
if isinstance(tab, tabs.MucTab):
- muc.leave_groupchat(self.xmpp, tab.get_room().name, tab.get_room().own_nick, msg)
+ muc.leave_groupchat(self.xmpp, tab.name, tab.own_nick, msg)
roster.empty()
self.save_config()
# Ugly fix thanks to gmail servers
@@ -1577,7 +1560,6 @@ class Core(object):
def remove_timed_event(self, event):
if event and event in self.timed_events:
- log.debug('removing event')
self.timed_events.remove(event)
def add_timed_event(self, event):
diff --git a/src/room.py b/src/room.py
deleted file mode 100644
index ad52451c..00000000
--- a/src/room.py
+++ /dev/null
@@ -1,132 +0,0 @@
-# Copyright 2010-2011 Florent Le Coz <louiz@louiz.org>
-#
-# This file is part of Poezio.
-#
-# Poezio is free software: you can redistribute it and/or modify
-# it under the terms of the zlib license. See the COPYING file.
-
-from text_buffer import TextBuffer, Message
-from datetime import datetime
-from random import randrange
-from config import config
-from logger import logger
-
-import common
-from theming import get_theme
-
-import logging
-import curses
-
-log = logging.getLogger(__name__)
-
-class Room(TextBuffer):
- def __init__(self, name, nick, messages_nb_limit=config.get('max_messages_in_memory', 2048)):
- TextBuffer.__init__(self, messages_nb_limit)
- self.name = name
- self.own_nick = nick
- self.state = 'normal' # color used in RoomInfo
- self.joined = False # false until self presence is receied
- self.users = [] # User objects
- self.topic = ''
-
- def disconnect(self):
- """
- Set the state of the room as not joined, so
- we can know if we can join it, send messages to it, etc
- """
- self.users = []
- self.state = 'disconnected'
- self.joined = False
-
- def get_single_line_topic(self):
- """
- Return the topic as a single-line string (for the window header)
- """
- return self.topic.replace('\n', '|')
-
- def log_message(self, txt, time, nickname):
- """
- Log the messages in the archives, if it needs
- to be
- """
- if time is None and self.joined: # don't log the history messages
- logger.log_message(self.name, nickname, txt)
-
- def do_highlight(self, txt, time, nickname):
- """
- Set the tab color and returns the nick color
- """
- color = None
- if not time and nickname and nickname != self.own_nick and self.joined:
- if self.own_nick.lower() in txt.lower():
- if self.state != 'current':
- self.state = 'highlight'
- color = get_theme().COLOR_HIGHLIGHT_NICK
- else:
- highlight_words = config.get('highlight_on', '').split(':')
- for word in highlight_words:
- if word and word.lower() in txt.lower():
- if self.state != 'current':
- self.state = 'highlight'
- color = get_theme().COLOR_HIGHLIGHT_NICK
- break
- if color:
- beep_on = config.get('beep_on', 'highlight private').split()
- if 'highlight' in beep_on and 'message' not in beep_on:
- curses.beep()
- return color
-
- def get_user_by_name(self, nick):
- """
- Gets the user associated with the given nick, or None if not found
- """
- for user in self.users:
- if user.nick == nick:
- return user
- return None
-
- def add_message(self, txt, time=None, nickname=None, forced_user=None, nick_color=None, history=None):
- """
- Note that user can be None even if nickname is not None. It happens
- when we receive an history message said by someone who is not
- in the room anymore
- """
- self.log_message(txt, time, nickname)
- special_message = False
- if txt.startswith('/me '):
- txt = "\x192}* \x195}" + nickname + ' ' + txt[4:]
- special_message = True
- user = self.get_user_by_name(nickname) if nickname is not None else None
- if user:
- user.set_last_talked(datetime.now())
- if not user and forced_user:
- user = forced_user
- if not time and nickname and\
- nickname != self.own_nick and\
- self.state != 'current':
- if self.state != 'highlight':
- self.state = 'message'
- nick_color = nick_color or None
- if not nickname or time:
- txt = '\x195}%s' % (txt,)
- else: # TODO
- highlight = self.do_highlight(txt, time, nickname)
- if highlight:
- nick_color = highlight
- if special_message:
- txt = '\x195}%s' % (txt,)
- nickname = None
- time = time or datetime.now()
- message = Message(txt='%s\x19o'%(txt.replace('\t', ' '),), nick_color=nick_color,
- time=time, str_time=time.strftime("%Y-%m-%d %H:%M:%S")\
- if history else time.strftime("%H:%M:%S"),\
- nickname=nickname, user=user)
- while len(self.messages) > self.messages_nb_limit:
- self.messages.pop(0)
- self.messages.append(message)
- for window in self.windows: # make the associated windows
- # build the lines from the new message
- nb = window.build_new_message(message, history=history)
- if window.pos != 0:
- window.scroll_up(nb)
- return nb
diff --git a/src/tabs.py b/src/tabs.py
index 9fe685a3..6afb0dd1 100644
--- a/src/tabs.py
+++ b/src/tabs.py
@@ -234,15 +234,6 @@ class Tab(object):
"""
self.state = 'current'
- def add_message(self):
- """
- Adds a message in the tab.
- If the tab cannot add a message in itself (for example
- FormTab, where text is not intented to be appened), it returns False.
- If the tab can, it returns True
- """
- return False
-
def on_scroll_down(self):
"""
Defines what happens when we scrol down
@@ -410,15 +401,20 @@ class MucTab(ChatTab):
It contains an userlist, an input, a topic, an information and a chat zone
"""
message_type = 'groupchat'
- def __init__(self, room):
- ChatTab.__init__(self, room)
+ def __init__(self, jid, nick):
+ ChatTab.__init__(self)
+ self.own_nick = nick
+ self.name = jid
+ self.joined = False
+ self.users = []
+ self.topic = ''
self.remote_wants_chatstates = True
# We send active, composing and paused states to the MUC because
# the chatstate may or may not be filtered by the MUC,
# that’s not our problem.
self.topic_win = windows.Topic()
self.text_win = windows.TextWin()
- room.add_window(self.text_win)
+ self._text_buffer.add_window(self.text_win)
self.v_separator = windows.VerticalSeparator()
self.user_win = windows.UserList()
self.info_header = windows.MucInfoWin()
@@ -793,7 +789,7 @@ class MucTab(ChatTab):
self.user_win.refresh(self.users)
self.info_header.refresh(self, self.text_win)
self.tab_win.refresh()
- self.info_win.refresh(self.core.informations)
+ self.info_win.refresh()
self.input.refresh()
def on_input(self, key):
@@ -839,9 +835,6 @@ class MucTab(ChatTab):
def get_text_window(self):
return self.text_win
- # def get_room(self):
- # return self._room
-
@property
def state(self):
return self._room.state
@@ -974,7 +967,7 @@ class MucTab(ChatTab):
by = by.attrib['jid'] if by is not None else None
if from_nick == self.own_nick: # we are banned
self.disconnect()
- self.core.disable_private_tabs(room.name)
+ self.core.disable_private_tabs(self.name)
self.tab_win.refresh()
self.core.doupdate()
if by:
@@ -989,19 +982,19 @@ class MucTab(ChatTab):
kick_msg = _('\x191}%(spec)s \x19%(color)d}%(nick)s\x195} has been banned') % {'spec':get_theme().CHAR_KICK, 'nick':from_nick.replace('"', '\\"'), 'color':color}
if reason is not None and reason.text:
kick_msg += _('\x195} Reason: \x196}%(reason)s\x195}') % {'reason': reason.text}
- room.add_message(kick_msg)
+ self._text_buffer.add_message(kick_msg)
- def on_user_kicked(self, room, presence, user, from_nick):
+ def on_user_kicked(self, presence, user, from_nick):
"""
When someone is kicked from a muc
"""
- room.users.remove(user)
+ self.users.remove(user)
by = presence.find('{%s}x/{%s}item/{%s}actor' % (NS_MUC_USER, NS_MUC_USER, NS_MUC_USER))
reason = presence.find('{%s}x/{%s}item/{%s}reason' % (NS_MUC_USER, NS_MUC_USER, NS_MUC_USER))
by = by.attrib['jid'] if by is not None else None
- if from_nick == room.own_nick: # we are kicked
- room.disconnect()
- self.core.disable_private_tabs(room.name)
+ if from_nick == self.own_nick: # we are kicked
+ self.disconnect()
+ self.core.disable_private_tabs(self.name)
self.tab_win.refresh()
self.core.doupdate()
if by:
@@ -1010,7 +1003,7 @@ class MucTab(ChatTab):
kick_msg = _('\x191}%(spec)s \x193}You\x195} have been kicked.') % {'spec':get_theme().CHAR_KICK}
# try to auto-rejoin
if config.get('autorejoin', 'false') == 'true':
- muc.join_groupchat(self.core.xmpp, room.name, room.own_nick)
+ muc.join_groupchat(self.core.xmpp, self.name, self.own_nick)
else:
color = user.color[0] if config.get('display_user_color_in_join_part', '') == 'true' else 3
if by:
@@ -1019,16 +1012,16 @@ class MucTab(ChatTab):
kick_msg = _('\x191}%(spec)s \x19%(color)d}%(nick)s\x195} has been kicked') % {'spec':get_theme().CHAR_KICK, 'nick':from_nick.replace('"', '\\"'), 'color':color}
if reason is not None and reason.text:
kick_msg += _('\x195} Reason: \x196}%(reason)s') % {'reason': reason.text}
- room.add_message(kick_msg)
+ self.add_message(kick_msg)
- def on_user_leave_groupchat(self, room, user, jid, status, from_nick, from_room):
+ def on_user_leave_groupchat(self, user, jid, status, from_nick, from_room):
"""
When an user leaves a groupchat
"""
- room.users.remove(user)
- if room.own_nick == user.nick:
+ self.users.remove(user)
+ if self.own_nick == user.nick:
# We are now out of the room. Happens with some buggy (? not sure) servers
- room.disconnect()
+ self.disconnect()
self.core.disable_private_tabs(from_room)
self.tab_win.refresh()
self.core.doupdate()
@@ -1042,11 +1035,11 @@ class MucTab(ChatTab):
leave_msg = _('\x191}%(spec)s \x19%(color)d}%(nick)s\x195} (\x194}%(jid)s\x195}) has left the room') % {'spec':get_theme().CHAR_QUIT, 'nick':from_nick, 'color':color, 'jid':jid.full}
if status:
leave_msg += ' (%s)' % status
- room.add_message(leave_msg)
+ self.add_message(leave_msg)
self.core.refresh_window()
self.core.on_user_left_private_conversation(from_room, from_nick, status)
- def on_user_change_status(self, room, user, from_nick, from_room, affiliation, role, show, status):
+ def on_user_change_status(self, user, from_nick, from_room, affiliation, role, show, status):
"""
When an user changes her status
"""
@@ -1054,7 +1047,7 @@ class MucTab(ChatTab):
display_message = False # flag to know if something significant enough
# to be displayed has changed
color = user.color[0] if config.get('display_user_color_in_join_part', '') == 'true' else 3
- if from_nick == room.own_nick:
+ if from_nick == self.own_nick:
msg = _('\x193}You\x195} changed: ')
else:
msg = _('\x19%(color)d}%(nick)s\x195} changed: ') % {'nick': from_nick.replace('"', '\\"'), 'color': color}
@@ -1086,27 +1079,119 @@ class MucTab(ChatTab):
hide_status_change = -1
if (hide_status_change == -1 or \
user.has_talked_since(hide_status_change) or\
- user.nick == room.own_nick)\
+ user.nick == self.own_nick)\
and\
(affiliation != user.affiliation or\
role != user.role or\
show != user.show or\
status != user.status):
# display the message in the room
- room.add_message(msg)
+ self._text_buffer.add_message(msg)
self.core.on_user_changed_status_in_private('%s/%s' % (from_room, from_nick), msg)
# finally, effectively change the user status
user.update(affiliation, show, status, role)
+ def disconnect(self):
+ """
+ Set the state of the room as not joined, so
+ we can know if we can join it, send messages to it, etc
+ """
+ self.users = []
+ self.state = 'disconnected'
+ self.joined = False
+
+ def get_single_line_topic(self):
+ """
+ Return the topic as a single-line string (for the window header)
+ """
+ return self.topic.replace('\n', '|')
+
+ def log_message(self, txt, time, nickname):
+ """
+ Log the messages in the archives, if it needs
+ to be
+ """
+ if time is None and self.joined: # don't log the history messages
+ logger.log_message(self.name, nickname, txt)
+
+ def do_highlight(self, txt, time, nickname):
+ """
+ Set the tab color and returns the nick color
+ """
+ color = None
+ if not time and nickname and nickname != self.own_nick and self.joined:
+ if self.own_nick.lower() in txt.lower():
+ if self.state != 'current':
+ self.state = 'highlight'
+ color = get_theme().COLOR_HIGHLIGHT_NICK
+ else:
+ highlight_words = config.get('highlight_on', '').split(':')
+ for word in highlight_words:
+ if word and word.lower() in txt.lower():
+ if self.state != 'current':
+ self.state = 'highlight'
+ color = get_theme().COLOR_HIGHLIGHT_NICK
+ break
+ if color:
+ beep_on = config.get('beep_on', 'highlight private').split()
+ if 'highlight' in beep_on and 'message' not in beep_on:
+ curses.beep()
+ return color
+
+ def get_user_by_name(self, nick):
+ """
+ Gets the user associated with the given nick, or None if not found
+ """
+ for user in self.users:
+ if user.nick == nick:
+ return user
+ return None
+
+ def add_message(self, txt, time=None, nickname=None, forced_user=None, nick_color=None, history=None):
+ """
+ Note that user can be None even if nickname is not None. It happens
+ when we receive an history message said by someone who is not
+ in the room anymore
+ """
+ self.log_message(txt, time, nickname)
+ special_message = False
+ if txt.startswith('/me '):
+ txt = "\x192}* \x195}" + nickname + ' ' + txt[4:]
+ special_message = True
+ user = self.get_user_by_name(nickname) if nickname is not None else None
+ if user:
+ user.set_last_talked(datetime.now())
+ if not user and forced_user:
+ user = forced_user
+ if not time and nickname and\
+ nickname != self.own_nick and\
+ self.state != 'current':
+ if self.state != 'highlight':
+ self.state = 'message'
+ nick_color = nick_color or None
+ if not nickname or time:
+ txt = '\x195}%s' % (txt,)
+ else: # TODO
+ highlight = self.do_highlight(txt, time, nickname)
+ if highlight:
+ nick_color = highlight
+ if special_message:
+ txt = '\x195}%s' % (txt,)
+ nickname = None
+ time = time or datetime.now()
+ self._text_buffer.add_message(txt, time, nickname, nick_color, history, user)
+
class PrivateTab(ChatTab):
"""
The tab containg a private conversation (someone from a MUC)
"""
message_type = 'chat'
- def __init__(self, room):
- ChatTab.__init__(self, room)
+ def __init__(self, name, nick):
+ ChatTab.__init__(self)
+ self.own_nick = nick
+ self.name = name
self.text_win = windows.TextWin()
- room.add_window(self.text_win)
+ self._text_buffer.add_window(self.text_win)
self.info_header = windows.PrivateInfoWin()
self.input = windows.MessageInput()
# keys
@@ -1117,7 +1202,7 @@ class PrivateTab(ChatTab):
self.commands['close'] = (self.command_unquery, _("Usage: /close\nClose: close the tab"), None)
self.commands['version'] = (self.command_version, _('Usage: /version\nVersion: get the software version of the current interlocutor (usually its XMPP client and Operating System)'), None)
self.resize()
- self.parent_muc = self.core.get_tab_by_name(JID(room.name).bare, MucTab)
+ self.parent_muc = self.core.get_tab_by_name(JID(name).bare, MucTab)
self.on = True
def completion(self):
@@ -1137,10 +1222,9 @@ class PrivateTab(ChatTab):
needed = 'inactive' if self.core.status.show in ('xa', 'away') else 'active'
msg['chat_state'] = needed
msg.send()
- self.core.add_message_to_text_buffer(self.get_room(), line, None, self.core.own_nick or self.get_room().own_nick)
- logger.log_message(JID(self.get_name()).bare, self.core.own_nick, line)
+ self.core.add_message_to_text_buffer(self._text_buffer, line, None, self.core.own_nick or self.own_nick)
self.cancel_paused_delay()
- self.text_win.refresh(self._room)
+ self.text_win.refresh()
self.input.refresh()
def command_unquery(self, arg):
@@ -1161,7 +1245,7 @@ class PrivateTab(ChatTab):
res.get('version') or _('unknown'),
res.get('os') or _('on an unknown platform'))
self.core.information(version, 'Info')
- jid = self.get_room().name
+ jid = self.name
self.core.xmpp.plugin['xep_0092'].get_version(jid, callback=callback)
def command_info(self, arg):
@@ -1171,7 +1255,7 @@ class PrivateTab(ChatTab):
if arg:
self.parent_muc.command_info(arg)
else:
- user = JID(self.get_room().name).resource
+ user = JID(self.name).resource
self.parent_muc.command_info(user)
def resize(self):
@@ -1179,7 +1263,7 @@ class PrivateTab(ChatTab):
return
self.need_resize = False
self.text_win.resize(self.height-3-self.core.information_win_size, self.width, 0, 0)
- self.text_win.rebuild_everything(self._room)
+ self.text_win.rebuild_everything(self._text_buffer)
self.info_header.resize(1, self.width, self.height-3-self.core.information_win_size, 0)
self.input.resize(1, self.width, self.height-1, 0)
@@ -1187,14 +1271,14 @@ class PrivateTab(ChatTab):
if self.need_resize:
self.resize()
log.debug(' TAB Refresh: %s'%self.__class__.__name__)
- self.text_win.refresh(self._room)
- self.info_header.refresh(self._room, self.text_win, self.chatstate)
- self.info_win.refresh(self.core.informations)
+ self.text_win.refresh()
+ self.info_header.refresh(self.name, self.text_win, self.chatstate)
+ self.info_win.refresh()
self.tab_win.refresh()
self.input.refresh()
def refresh_info_header(self):
- self.info_header.refresh(self._room, self.text_win, self.chatstate)
+ self.info_header.refresh(self.name, self.text_win, self.chatstate)
self.input.refresh()
@property
@@ -1206,7 +1290,7 @@ class PrivateTab(ChatTab):
self._room.state = value
def get_name(self):
- return self._room.name
+ return self.name
def on_input(self, key):
if key in self.key_func:
@@ -1216,8 +1300,8 @@ class PrivateTab(ChatTab):
if not self.on:
return False
empty_after = self.input.get_text() == '' or (self.input.get_text().startswith('/') and not self.input.get_text().startswith('//'))
- tab = self.core.get_tab_by_name(JID(self.get_room().name).bare, MucTab)
- if tab and tab.get_room().joined:
+ tab = self.core.get_tab_by_name(JID(self.name).bare, MucTab)
+ if tab and tab.joined:
self.send_composing_chat_state(empty_after)
return False
@@ -1225,13 +1309,15 @@ class PrivateTab(ChatTab):
self.state = 'normal'
self.text_win.remove_line_separator()
self.text_win.add_line_separator()
- if self.get_room().joined and config.get('send_chat_states', 'true') == 'true' and not self.input.get_text():
+ tab = self.core.get_tab_by_name(JID(self.name).bare, MucTab)
+ if tab.joined and config.get('send_chat_states', 'true') == 'true' and not self.input.get_text():
self.send_chat_state('inactive')
def on_gain_focus(self):
self.state = 'current'
curses.curs_set(1)
- if self.get_room().joined and config.get('send_chat_states', 'true') == 'true' and not self.input.get_text():
+ tab = self.core.get_tab_by_name(JID(self.name).bare, MucTab)
+ if tab.joined and config.get('send_chat_states', 'true') == 'true' and not self.input.get_text():
self.send_chat_state('active')
def on_scroll_up(self):
@@ -1246,9 +1332,6 @@ class PrivateTab(ChatTab):
self.text_win.resize(self.height-3-self.core.information_win_size, self.width, 0, 0)
self.info_header.resize(1, self.width, self.height-3-self.core.information_win_size, 0)
- def get_room(self):
- return self._room
-
def get_text_window(self):
return self.text_win
@@ -1257,9 +1340,9 @@ class PrivateTab(ChatTab):
The user changed her nick in the corresponding muc: update the tab’s name and
display a message.
"""
- self.get_room().add_message(_('"[%(old_nick)s]" is now known as "[%(new_nick)s]"') % {'old_nick':old_nick.replace('"', '\\"'), 'new_nick':new_nick.replace('"', '\\"')})
- new_jid = JID(self.get_room().name).bare+'/'+new_nick
- self.get_room().name = new_jid
+ self.add_message('\x193}%(old)s\x195} is now known as \x193}%(new)s' % {'old':old_nick, 'new':new_nick})
+ new_jid = JID(self.name).bare+'/'+new_nick
+ self.name = new_jid
def user_left(self, status_message, from_nick):
"""
@@ -1267,9 +1350,9 @@ class PrivateTab(ChatTab):
"""
self.deactivate()
if not status_message:
- self.get_room().add_message(_('\x191}%(spec)s \x193}%(nick)s\x195} has left the room') % {'nick':from_nick.replace('"', '\\"'), 'spec':get_theme().CHAR_QUIT.replace('"', '\\"')})
+ self.add_message(_('\x191}%(spec)s \x193}%(nick)s\x195} has left the room') % {'nick':from_nick.replace('"', '\\"'), 'spec':get_theme().CHAR_QUIT.replace('"', '\\"')})
else:
- self.get_room().add_message(_('\x191}%(spec)s \x193}%(nick)s\x195} has left the room (%(status)s)"') % {'nick':from_nick.replace('"', '\\"'), 'spec':get_theme().CHAR_QUIT, 'status': status_message.replace('"', '\\"')})
+ self.add_message(_('\x191}%(spec)s \x193}%(nick)s\x195} has left the room (%(status)s)"') % {'nick':from_nick.replace('"', '\\"'), 'spec':get_theme().CHAR_QUIT, 'status': status_message.replace('"', '\\"')})
if self.core.current_tab() is self:
self.refresh()
self.core.doupdate()
@@ -1279,18 +1362,26 @@ class PrivateTab(ChatTab):
The user (or at least someone with the same nick) came back in the MUC
"""
self.activate()
- self.get_room().add_message('\x194}%(spec)s \x19%(color)d}%(nick)s\x195} joined the room' % {'nick':nick, 'color':user.color, 'spec':get_theme().CHAR_JOIN})
+ tab = self.core.get_tab_by_name(JID(self.name).bare, MucTab)
+ color = None
+ if tab:
+ user = tab.get_user_by_name(nick)
+ if user:
+ color = user.color
+ self.add_message('\x194}%(spec)s \x19%(color)d}%(nick)s\x195} joined the room' % {'nick':nick, 'color': color or 3, 'spec':get_theme().CHAR_JOIN})
if self.core.current_tab() is self:
self.refresh()
self.core.doupdate()
-
def activate(self):
self.on = True
def deactivate(self):
self.on = False
+ def add_message(self, txt, time=None, nickname=None, forced_user=None):
+ self._text_buffer.add_message(txt, time, nickname, None, None, forced_user)
+
class RosterInfoTab(Tab):
"""
A tab, splitted in two, containing the roster and infos
@@ -1675,9 +1766,6 @@ class RosterInfoTab(Tab):
else:
curses.curs_set(1)
- def add_message(self):
- return False
-
def move_cursor_down(self):
if isinstance(self.input, windows.CommandInput):
return
@@ -1774,12 +1862,11 @@ class ConversationTab(ChatTab):
"""
message_type = 'chat'
def __init__(self, jid):
- txt_buff = text_buffer.TextBuffer()
- ChatTab.__init__(self, txt_buff)
+ ChatTab.__init__(self)
self.state = 'normal'
self._name = jid # a conversation tab is linked to one specific full jid OR bare jid
self.text_win = windows.TextWin()
- txt_buff.add_window(self.text_win)
+ self._text_buffer.add_window(self.text_win)
self.upper_bar = windows.ConversationStatusMessageWin()
self.info_header = windows.ConversationInfoWin()
self.input = windows.MessageInput()
@@ -1805,10 +1892,10 @@ class ConversationTab(ChatTab):
needed = 'inactive' if self.core.status.show in ('xa', 'away') else 'active'
msg['chat_state'] = needed
msg.send()
- self.core.add_message_to_text_buffer(self.get_room(), line, None, self.core.own_nick)
+ self.core.add_message_to_text_buffer(self._text_buffer, line, None, self.core.own_nick)
logger.log_message(JID(self.get_name()).bare, self.core.own_nick, line)
self.cancel_paused_delay()
- self.text_win.refresh(self._room)
+ self.text_win.refresh()
self.input.refresh()
def command_unquery(self, arg):
@@ -1819,7 +1906,7 @@ class ConversationTab(ChatTab):
return
self.need_resize = False
self.text_win.resize(self.height-4-self.core.information_win_size, self.width, 1, 0)
- self.text_win.rebuild_everything(self._room)
+ self.text_win.rebuild_everything(self._text_buffer)
self.upper_bar.resize(1, self.width, 0, 0)
self.info_header.resize(1, self.width, self.height-3-self.core.information_win_size, 0)
self.input.resize(1, self.width, self.height-1, 0)
@@ -1828,15 +1915,15 @@ class ConversationTab(ChatTab):
if self.need_resize:
self.resize()
log.debug(' TAB Refresh: %s'%self.__class__.__name__)
- self.text_win.refresh(self._room)
+ self.text_win.refresh()
self.upper_bar.refresh(self.get_name(), roster.get_contact_by_jid(self.get_name()))
- self.info_header.refresh(self.get_name(), roster.get_contact_by_jid(self.get_name()), self._room, self.text_win, self.chatstate)
- self.info_win.refresh(self.core.informations)
+ self.info_header.refresh(self.get_name(), roster.get_contact_by_jid(self.get_name()), self.text_win, self.chatstate)
+ self.info_win.refresh()
self.tab_win.refresh()
self.input.refresh()
def refresh_info_header(self):
- self.info_header.refresh(self.get_name(), roster.get_contact_by_jid(self.get_name()), self._room, self.text_win, self.chatstate)
+ self.info_header.refresh(self.get_name(), roster.get_contact_by_jid(self.get_name()), self.text_win, self.chatstate)
self.input.refresh()
def get_name(self):
@@ -1876,9 +1963,6 @@ class ConversationTab(ChatTab):
self.text_win.resize(self.height-4-self.core.information_win_size, self.width, 1, 0)
self.info_header.resize(1, self.width, self.height-3-self.core.information_win_size, 0)
- def get_room(self):
- return self._room
-
def get_text_window(self):
return self.text_win
diff --git a/src/text_buffer.py b/src/text_buffer.py
index f39f147a..eb4b7b79 100644
--- a/src/text_buffer.py
+++ b/src/text_buffer.py
@@ -34,19 +34,20 @@ class TextBuffer(object):
def add_window(self, win):
self.windows.append(win)
- def add_message(self, txt, time=None, nickname=None, nick_color=None, history=None):
+ def add_message(self, txt, time=None, nickname=None, nick_color=None, history=None, user=None):
time = time or datetime.now()
msg = Message(txt='%s\x19o'%(txt.replace('\t', ' '),), nick_color=nick_color,
time=time, str_time=time.strftime("%Y-%m-%d %H:%M:%S")\
if history else time.strftime("%H:%M:%S"),\
- nickname=nickname, user=None)
+ nickname=nickname, user=user)
+ log.debug('Coucou, le message ajouté : %s' % (msg,))
self.messages.append(msg)
while len(self.messages) > self.messages_nb_limit:
self.messages.pop(0)
ret_val = None
for window in self.windows: # make the associated windows
# build the lines from the new message
- nb = window.build_new_message(msg)
+ nb = window.build_new_message(msg, history=history)
if ret_val is None:
ret_val = nb
if window.pos != 0:
diff --git a/src/windows.py b/src/windows.py
index dfe46a14..42c9bfa0 100644
--- a/src/windows.py
+++ b/src/windows.py
@@ -341,18 +341,18 @@ class PrivateInfoWin(InfoWin):
def __init__(self):
InfoWin.__init__(self)
- def refresh(self, room, window, chatstate):
+ def refresh(self, name, window, chatstate):
log.debug('Refresh: %s'%self.__class__.__name__)
with g_lock:
self._win.erase()
- self.write_room_name(room)
+ self.write_room_name(name)
self.print_scroll_position(window)
self.write_chatstate(chatstate)
self.finish_line(get_theme().COLOR_INFORMATION_BAR)
self._refresh()
- def write_room_name(self, room):
- jid = JID(room.name)
+ def write_room_name(self, name):
+ jid = JID(name)
room_name, nick = jid.bare, jid.resource
self.addstr(nick, to_curses_attr(get_theme().COLOR_PRIVATE_NAME))
txt = ' from room %s' % room_name
@@ -380,7 +380,7 @@ class ConversationInfoWin(InfoWin):
def __init__(self):
InfoWin.__init__(self)
- def refresh(self, jid, contact, text_buffer, window, chatstate):
+ def refresh(self, jid, contact, window, chatstate):
# contact can be None, if we receive a message
# from someone not in our roster. In this case, we display
# only the maximum information from the message we can get.