Mor colored information message, also finish the theme 'engine'. fixed #1537

parent 3d278f78
...@@ -484,9 +484,9 @@ class Gui(object): ...@@ -484,9 +484,9 @@ class Gui(object):
hide_exit_join = config.get('hide_exit_join', -1) hide_exit_join = config.get('hide_exit_join', -1)
if hide_exit_join != 0: if hide_exit_join != 0:
if not jid: if not jid:
self.add_message_to_room(room, _("%(nick)s joined the room") % {'nick':from_nick}) self.add_message_to_room(room, _("%(spec)s [%(nick)s] joined the room") % {'nick':from_nick, 'spec':theme.CHAR_JOIN}, colorized=True)
else: else:
self.add_message_to_room(room, _("%(nick)s (%(jid)s) joined the room") % {'nick':from_nick, 'jid':jid}) self.add_message_to_room(room, _("%(spec)s [%(nick)s] (%(jid)s) joined the room") % {'spec':theme.CHAR_JOIN, 'nick':from_nick, 'jid':jid}, colorized=True)
# nick change # nick change
elif change_nick: elif change_nick:
if user.nick == room.own_nick: if user.nick == room.own_nick:
...@@ -496,11 +496,11 @@ class Gui(object): ...@@ -496,11 +496,11 @@ class Gui(object):
if _room.jid is not None and is_jid_the_same(_room.jid, room.name): if _room.jid is not None and is_jid_the_same(_room.jid, room.name):
_room.own_nick = stanza.getNick() _room.own_nick = stanza.getNick()
user.change_nick(stanza.getNick()) user.change_nick(stanza.getNick())
self.add_message_to_room(room, _('%(old)s is now known as %(new)s') % {'old':from_nick, 'new':stanza.getNick()}) self.add_message_to_room(room, _('[%(old)s] is now known as [%(new)s]') % {'old':from_nick, 'new':stanza.getNick()}, colorized=True)
# rename the private tabs if needed # rename the private tabs if needed
private_room = self.get_room_by_name(stanza.getFrom()) private_room = self.get_room_by_name(stanza.getFrom())
if private_room: if private_room:
self.add_message_to_room(private_room, _('%(old_nick)s is now known as %(new_nick)s') % {'old_nick':from_nick, 'new_nick':stanza.getNick()}) self.add_message_to_room(private_room, _('[%(old_nick)s] is now known as [%(new_nick)s]') % {'old_nick':from_nick, 'new_nick':stanza.getNick()}, colorized=True)
new_jid = private_room.name.split('/')[0]+'/'+stanza.getNick() new_jid = private_room.name.split('/')[0]+'/'+stanza.getNick()
private_room.jid = new_jid private_room.jid = new_jid
private_room.name = new_jid private_room.name = new_jid
...@@ -519,29 +519,29 @@ class Gui(object): ...@@ -519,29 +519,29 @@ class Gui(object):
if from_nick == room.own_nick: # we are kicked if from_nick == room.own_nick: # we are kicked
room.disconnect() room.disconnect()
if by: if by:
self.add_message_to_room(room, _("You have been kicked by %(by)s. Reason: %(reason)s") % {'by':by, 'reason':reason}) self.add_message_to_room(room, _("%(spec) [You] have been kicked by [%(by)s]. Reason: {%(reason)s}") % {'spec': theme.CHAR_KICK, 'by':by, 'reason':reason}, colorized=True)
else: else:
self.add_message_to_room(room, _("You have been kicked. Reason: %s") % (reason)) self.add_message_to_room(room, _("%(spec)s [You] have been kicked. Reason: %(reason)s") % {'reason':reason, 'spec':theme.CHAR_KICK}, colorized=True)
# try to auto-rejoin # try to auto-rejoin
if config.get('autorejoin', 'false') == 'true': if config.get('autorejoin', 'false') == 'true':
self.muc.join_room(room.name, room.own_nick) self.muc.join_room(room.name, room.own_nick)
else: else:
if by: if by:
self.add_message_to_room(room, _("%(nick)s has been kicked by %(by)s. Reason: %(reason)s") % {'nick':from_nick, 'by':by, 'reason':reason}) self.add_message_to_room(room, _("%(spec)s [%(nick)s] has been kicked by %(by)s. Reason: %(reason)s") % {'spec':theme.CHAR_KICK, 'nick':from_nick, 'by':by, 'reason':reason}, colorized=True)
else: else:
self.add_message_to_room(room, _("%(nick)s has been kicked. Reason: %(reason)s") % {'nick':from_nick, 'reason':reason}) self.add_message_to_room(room, _("%(spec)s [%(nick)s] has been kicked. Reason: %(reason)s") % {'nick':from_nick, 'reason':reason, 'spec':theme.CHAR_KICK}, colorized=True)
# user quit # user quit
elif status == 'offline' or role == 'none': elif status == 'offline' or role == 'none':
room.users.remove(user) room.users.remove(user)
hide_exit_join = config.get('hide_exit_join', -1) if config.get('hide_exit_join', -1) >= -1 else -1 hide_exit_join = config.get('hide_exit_join', -1) if config.get('hide_exit_join', -1) >= -1 else -1
if hide_exit_join == -1 or user.has_talked_since(hide_exit_join): if hide_exit_join == -1 or user.has_talked_since(hide_exit_join):
if not jid: if not jid:
self.add_message_to_room(room, _('%s has left the room') % (from_nick)) self.add_message_to_room(room, _('%(spec)s [%(nick)s] has left the room') % {'nick':from_nick, 'spec':theme.CHAR_QUIT}, colorized=True)
else: else:
self.add_message_to_room(room, _('%(nick)s (%(jid)s) has left the room') % {'nick':from_nick, 'jid':jid}) self.add_message_to_room(room, _('%(spec)s [%(nick)s] (%(jid)s) has left the room') % {'spec':theme.CHAR_QUIT, 'nick':from_nick, 'jid':jid}, colorized=True)
private_room = self.get_room_by_name(stanza.getFrom()) private_room = self.get_room_by_name(stanza.getFrom())
if private_room: if private_room:
self.add_message_to_room(private_room, _('%s has left the room') % (from_nick)) self.add_message_to_room(private_room, _('%(spec)s [%(nick)s] has left the room') % {'nick':from_nick, 'spec':theme.CHAR_KICK}, colorized=True)
# status change # status change
else: else:
# build the message # build the message
...@@ -576,14 +576,14 @@ class Gui(object): ...@@ -576,14 +576,14 @@ class Gui(object):
self.window.input.refresh() self.window.input.refresh()
doupdate() doupdate()
def add_message_to_room(self, room, txt, time=None, nickname=None): def add_message_to_room(self, room, txt, time=None, nickname=None, colorized=False):
""" """
Add the message to the room and refresh the associated component Add the message to the room and refresh the associated component
of the interface of the interface
""" """
if room != self.current_room(): if room != self.current_room():
room.add_line_separator() room.add_line_separator()
room.add_message(txt, time, nickname) room.add_message(txt, time, nickname, colorized)
if room == self.current_room(): if room == self.current_room():
self.window.text_win.refresh(room) self.window.text_win.refresh(room)
else: else:
......
...@@ -21,21 +21,25 @@ from datetime import datetime ...@@ -21,21 +21,25 @@ from datetime import datetime
class Message(object): class Message(object):
""" """
A message with all the associated data (nickname, time, color, etc) A message with all the associated data (nickname, time, color, etc)
The color can be a single number OR a list of numbers, for
specials cases like join or quit messages.
""" """
def __init__(self, txt, time=None, nickname=None, user=None, color=None): def __init__(self, txt, time=None, nickname=None, user=None, color=None, colorized=False):
""" """
time is a datetime object, None means 'now'. time is a datetime object, None means 'now'.
If no nickname is specified, it's an information. If no nickname is specified, it's an information.
user is an User object (used for the color, etc) user is an User object (used for the color, etc)
""" """
self.txt = txt self.txt = txt
self.nickname = nickname self.nickname = nickname
self.time = time self.time = time
self.user = user self.user = user
self.color = color self.color = color
self.colorized = colorized
def __repr__(self): def __repr__(self):
return "<Message txt=%s, nickname=%s, time=%s, user=%s>" % (self.txt, self.nickname, str(self.time), str(self.user)) return "<Message txt=%s, nickname=%s, time=%s, user=%s, colorized=%s>" % (self.txt, self.nickname, str(self.time), str(self.user), self.colorized)
def __str__(self): def __str__(self):
return self.__repr__() return self.__repr__()
...@@ -43,6 +47,8 @@ class Line(object): ...@@ -43,6 +47,8 @@ class Line(object):
""" """
A line, corresponding to ONE row of the text area. A line, corresponding to ONE row of the text area.
A message is composed of ONE line or MORE. A message is composed of ONE line or MORE.
The same particularity for colors in Message class applies
here too.
Example: Example:
Text area limit text area limit Text area limit text area limit
...@@ -67,10 +73,11 @@ class Line(object): ...@@ -67,10 +73,11 @@ class Line(object):
Line(None, None, None, "informations here:", 0, 23) Line(None, None, None, "informations here:", 0, 23)
Line(None, None, None, "http://blablablabla", 0, 23) Line(None, None, None, "http://blablablabla", 0, 23)
""" """
def __init__(self, nickname, nickname_color, time, text, text_color, text_offset): def __init__(self, nickname, nickname_color, time, text, text_color, text_offset, colorized=False):
self.nickname = nickname self.nickname = nickname
self.nickname_color = nickname_color self.nickname_color = nickname_color
self.time = time self.time = time
self.text = text self.text = text
self.text_color = text_color self.text_color = text_color
self.text_offset = text_offset self.text_offset = text_offset
self.colorized = colorized
...@@ -91,7 +91,7 @@ class Room(object): ...@@ -91,7 +91,7 @@ class Room(object):
break break
return color return color
def add_message(self, txt, time=None, nickname=None): def add_message(self, txt, time=None, nickname=None, colorized=False):
""" """
Note that user can be None even if nickname is not None. It happens 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 when we receive an history message said by someone who is not
...@@ -116,7 +116,7 @@ class Room(object): ...@@ -116,7 +116,7 @@ class Room(object):
if time: # History messages are colored to be distinguished if time: # History messages are colored to be distinguished
color = theme.COLOR_INFORMATION_TEXT color = theme.COLOR_INFORMATION_TEXT
time = time if time is not None else datetime.now() time = time if time is not None else datetime.now()
self.messages.append(Message(txt, time, nickname, user, color)) self.messages.append(Message(txt, time, nickname, user, color, colorized))
def remove_line_separator(self): def remove_line_separator(self):
""" """
......
...@@ -42,6 +42,10 @@ COLOR_USER_PARTICIPANT = 73 ...@@ -42,6 +42,10 @@ COLOR_USER_PARTICIPANT = 73
COLOR_USER_NONE = 80 COLOR_USER_NONE = 80
COLOR_USER_MODERATOR = 77 COLOR_USER_MODERATOR = 77
# The character printed in color (COLOR_STATUS_*) before the nickname
# in the user list
CHAR_STATUS = ' '
# Separators # Separators
COLOR_VERTICAL_SEPARATOR = 73 COLOR_VERTICAL_SEPARATOR = 73
COLOR_NEW_TEXT_SEPARATOR = 75 COLOR_NEW_TEXT_SEPARATOR = 75
...@@ -77,8 +81,24 @@ COLOR_TOPIC_BAR = 15 ...@@ -77,8 +81,24 @@ COLOR_TOPIC_BAR = 15
COLOR_PRIVATE_ROOM_BAR = 33 COLOR_PRIVATE_ROOM_BAR = 33
COLOR_SCROLLABLE_NUMBER = 16 COLOR_SCROLLABLE_NUMBER = 16
# Chars # Strings for special messages (like join, quit, nick change, etc)
STATUS_CHAR = ' '
# Special messages
CHAR_JOIN = '---->'
CHAR_QUIT = '<----'
CHAR_KICK = '-!-'
COLOR_JOIN_CHAR = 73
COLOR_QUIT_CHAR = 77
COLOR_KICK_CHAR = 77
# words between ()
COLOR_CURLYBRACKETED_WORD = 72
# words between {}
COLOR_ACCOLADE_WORD = 74
# words between []
COLOR_BRACKETED_WORD = 73
def init_colors(): def init_colors():
""" """
...@@ -123,7 +143,7 @@ def reload_theme(): ...@@ -123,7 +143,7 @@ def reload_theme():
except: # TODO warning: theme not found except: # TODO warning: theme not found
return return
for var in dir(theme): for var in dir(theme):
if var.startswith('COLOR_') or var.startswith('STATUS_'): if var.startswith('COLOR_') or var.startswith('CHAR_'):
globals()[var] = getattr(theme, var) globals()[var] = getattr(theme, var)
if __name__ == '__main__': if __name__ == '__main__':
......
...@@ -102,7 +102,7 @@ class UserList(Win): ...@@ -102,7 +102,7 @@ class UserList(Win):
except KeyError: except KeyError:
show_col = theme.COLOR_STATUS_NONE show_col = theme.COLOR_STATUS_NONE
self.win.attron(curses.color_pair(show_col)) self.win.attron(curses.color_pair(show_col))
self.win.addnstr(y, 0, theme.STATUS_CHAR, 1) self.win.addnstr(y, 0, theme.CHAR_STATUS, 1)
self.win.attroff(curses.color_pair(show_col)) self.win.attroff(curses.color_pair(show_col))
self.win.attron(curses.color_pair(role_col)) self.win.attron(curses.color_pair(role_col))
try: try:
...@@ -267,7 +267,8 @@ class TextWin(Win): ...@@ -267,7 +267,8 @@ class TextWin(Win):
l = Line(nick, color, l = Line(nick, color,
time, time,
txt[:limit], message.color, txt[:limit], message.color,
offset) offset,
message.colorized)
lines.append(l) lines.append(l)
if this_line_was_broken_by_space: if this_line_was_broken_by_space:
txt = txt[limit+1:] # jump the space at the start of the line txt = txt[limit+1:] # jump the space at the start of the line
...@@ -308,7 +309,7 @@ class TextWin(Win): ...@@ -308,7 +309,7 @@ class TextWin(Win):
self.write_time(line.time) self.write_time(line.time)
if line.nickname is not None: if line.nickname is not None:
self.write_nickname(line.nickname.encode('utf-8'), line.nickname_color) self.write_nickname(line.nickname.encode('utf-8'), line.nickname_color)
self.write_text(y, line.text_offset, line.text, line.text_color) self.write_text(y, line.text_offset, line.text, line.text_color, line.colorized)
y += 1 y += 1
self.win.refresh() self.win.refresh()
g_lock.release() g_lock.release()
...@@ -320,19 +321,49 @@ class TextWin(Win): ...@@ -320,19 +321,49 @@ class TextWin(Win):
self.win.addstr(' -'*(self.width/2)) self.win.addstr(' -'*(self.width/2))
self.win.attroff(curses.color_pair(theme.COLOR_NEW_TEXT_SEPARATOR)) self.win.attroff(curses.color_pair(theme.COLOR_NEW_TEXT_SEPARATOR))
def write_text(self, y, x, txt, color): def write_text(self, y, x, txt, color, colorized):
""" """
write the text of a line. write the text of a line.
""" """
txt = txt.encode('utf-8') txt = txt.encode('utf-8')
if color: if not colorized:
self.win.attron(curses.color_pair(color)) if color:
try: self.win.attron(curses.color_pair(color))
self.win.addstr(y, x, txt) try:
except: # bug 1665 self.win.addstr(y, x, txt)
pass except: # bug 1665
if color: pass
self.win.attroff(curses.color_pair(color)) if color:
self.win.attroff(curses.color_pair(color))
else: # Special messages like join or quit
from common import debug
special_words = {
theme.CHAR_JOIN: theme.COLOR_JOIN_CHAR,
theme.CHAR_QUIT: theme.COLOR_QUIT_CHAR,
theme.CHAR_KICK: theme.COLOR_KICK_CHAR,
}
for word in txt.split():
if word in special_words.keys():
self.win.attron(curses.color_pair(special_words[word]))
self.win.addstr(word)
self.win.attroff(curses.color_pair(special_words[word]))
elif word.startswith('(') and word.endswith(')'):
self.win.addstr('(', curses.color_pair(color))
self.win.addstr(word[1:-1], curses.color_pair(theme.COLOR_CURLYBRACKETED_WORD))
self.win.addstr(')', curses.color_pair(color))
elif word.startswith('{') and word.endswith('}'):
self.win.addstr(word[1:-1], curses.color_pair(theme.COLOR_ACCOLADE_WORD))
elif word.startswith('[') and word.endswith(']'):
self.win.addstr(word[1:-1], curses.color_pair(theme.COLOR_BRACKETED_WORD))
else:
self.win.attron(curses.color_pair(color))
self.win.addstr(word)
self.win.attroff(curses.color_pair(color))
try:
self.win.addstr(' ')
except:
pass
def write_nickname(self, nickname, color): def write_nickname(self, nickname, color):
""" """
...@@ -712,10 +743,7 @@ class Input(Win): ...@@ -712,10 +743,7 @@ class Input(Win):
Refresh the line onscreen, from the pos and pos_line Refresh the line onscreen, from the pos and pos_line
""" """
self.clear_text() self.clear_text()
try: # FIXME: this try should NOT be needed self.win.addstr(self.text[self.line_pos:self.line_pos+self.width-1].encode('utf-8'))
self.win.addstr(self.text[self.line_pos:self.line_pos+self.width-1].encode('utf-8'))
except:
pass
self.win.move(0, self.pos) self.win.move(0, self.pos)
self.refresh() self.refresh()
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment