From 26ea842cee32623aafea3f05d4a0b347428712c3 Mon Sep 17 00:00:00 2001 From: mathieui Date: Sat, 8 Jun 2013 17:36:02 +0200 Subject: Add a way to format background colors in a string (also add colors to the /info command in MUCs) --- src/core.py | 24 +++++----- src/tabs.py | 138 +++++++++++++++++++++++++++++++++++---------------------- src/theming.py | 52 ++++++++++++++++++++++ src/windows.py | 74 ++++++++++--------------------- 4 files changed, 172 insertions(+), 116 deletions(-) diff --git a/src/core.py b/src/core.py index fc3a5458..8a1a6be5 100644 --- a/src/core.py +++ b/src/core.py @@ -56,7 +56,7 @@ from roster import roster from contact import Contact, Resource from text_buffer import TextBuffer, CorrectionError from keyboard import keyboard -from theming import get_theme +from theming import get_theme, dump_tuple from fifo import Fifo from windows import g_lock from daemon import Executor @@ -1349,7 +1349,7 @@ class Core(object): """ args = arg.split() if not args: - color = get_theme().COLOR_HELP_COMMANDS[0] + color = dump_tuple(get_theme().COLOR_HELP_COMMANDS) acc = [] buff = ['Global commands:'] for command in self.commands: @@ -3344,22 +3344,22 @@ class Core(object): modif = False if show_unavailable or hide_unavailable or non_priv or logging_off\ or non_anon or semi_anon or full_anon: - tab.add_message('\x19%(info_col)s}Info: A configuration change not privacy-related occured.' % {'info_col': get_theme().COLOR_INFORMATION_TEXT[0]}) + tab.add_message('\x19%(info_col)s}Info: A configuration change not privacy-related occured.' % {'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)}) modif = True if show_unavailable: - tab.add_message('\x19%(info_col)s}Info: The unavailable members are now shown.' % {'info_col': get_theme().COLOR_INFORMATION_TEXT[0]}) + tab.add_message('\x19%(info_col)s}Info: The unavailable members are now shown.' % {'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)}) elif hide_unavailable: - tab.add_message('\x19%(info_col)s}Info: The unavailable members are now hidden.' % {'info_col': get_theme().COLOR_INFORMATION_TEXT[0]}) + tab.add_message('\x19%(info_col)s}Info: The unavailable members are now hidden.' % {'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)}) if non_anon: - tab.add_message('\x191}Warning:\x19%(info_col)s} The room is now not anonymous. (public JID)' % {'info_col': get_theme().COLOR_INFORMATION_TEXT[0]}) + tab.add_message('\x191}Warning:\x19%(info_col)s} The room is now not anonymous. (public JID)' % {'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)}) elif semi_anon: - tab.add_message('\x19%(info_col)s}Info: The room is now semi-anonymous. (moderators-only JID)' % {'info_col': get_theme().COLOR_INFORMATION_TEXT[0]}) + tab.add_message('\x19%(info_col)s}Info: The room is now semi-anonymous. (moderators-only JID)' % {'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)}) elif full_anon: - tab.add_message('\x19%(info_col)s}Info: The room is now fully anonymous.' % {'info_col': get_theme().COLOR_INFORMATION_TEXT[0]}) + tab.add_message('\x19%(info_col)s}Info: The room is now fully anonymous.' % {'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)}) if logging_on: - tab.add_message('\x191}Warning: \x19%(info_col)s}This room is publicly logged' % {'info_col': get_theme().COLOR_INFORMATION_TEXT[0]}) + tab.add_message('\x191}Warning: \x19%(info_col)s}This room is publicly logged' % {'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)}) elif logging_off: - tab.add_message('\x19%(info_col)s}Info: This room is not logged anymore.' % {'info_col': get_theme().COLOR_INFORMATION_TEXT[0]}) + tab.add_message('\x19%(info_col)s}Info: This room is not logged anymore.' % {'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)}) if modif: self.refresh_window() @@ -3376,11 +3376,11 @@ class Core(object): if nick_from: self.add_message_to_text_buffer(tab._text_buffer, _("\x19%(info_col)s}%(nick)s set the subject to: %(subject)s") % - {'info_col': get_theme().COLOR_INFORMATION_TEXT[0], 'nick':nick_from, 'subject':subject}, + {'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT), 'nick':nick_from, 'subject':subject}, time=None) else: self.add_message_to_text_buffer(tab._text_buffer, _("\x19%(info_col)s}The subject is: %(subject)s") % - {'subject':subject, 'info_col': get_theme().COLOR_INFORMATION_TEXT[0]}, + {'subject':subject, 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)}, time=None) tab.topic = subject if self.get_tab_by_name(room_from, tabs.MucTab) is self.current_tab(): diff --git a/src/tabs.py b/src/tabs.py index f99ba388..a66a3e61 100644 --- a/src/tabs.py +++ b/src/tabs.py @@ -38,7 +38,7 @@ import time import multiuserchat as muc -from theming import get_theme +from theming import get_theme, dump_tuple from common import safeJID from decorators import refresh_wrapper @@ -469,7 +469,7 @@ class ChatTab(Tab): logs = logger.get_logs(safeJID(self.get_name()).bare, log_nb) if logs: for log_line in logs: - log_line = '\x19%s}%s' % (get_theme().COLOR_INFORMATION_TEXT[0], log_line) + log_line = '\x19%s}%s' % (dump_tuple(get_theme().COLOR_INFORMATION_TEXT), log_line) self._text_buffer.add_message( txt=log_line.strip(), time='', @@ -920,10 +920,16 @@ class MucTab(ChatTab): user = self.get_user_by_name(arg) if not user: return self.core.information("Unknown user: %s" % arg) - info = '%s%s: show: %s, affiliation: %s, role: %s%s' % (arg, - ' (%s)' % user.jid if user.jid else '', + theme = get_theme() + info = '\x19%s}%s\x19o%s: show: \x19%s}%s\x19o, affiliation: \x19%s}%s\x19o, role: \x19%s}%s\x19o%s' % ( + dump_tuple(user.color), + arg, + (' (\x19%s}%s\x19o)' % (dump_tuple(theme.COLOR_MUC_JID), user.jid)) if user.jid != '' else '', + dump_tuple(theme.color_show(user.show)), user.show or 'Available', + dump_tuple(theme.color_role(user.role)), user.affiliation or 'None', + dump_tuple(theme.color_role(user.role)), user.role or 'None', '\n%s' % user.status if user.status else '') self.core.information(info, 'Info') @@ -1070,7 +1076,7 @@ class MucTab(ChatTab): """ if not arg.strip(): self._text_buffer.add_message(_("\x19%s}The subject of the room is: %s") % - (get_theme().COLOR_INFORMATION_TEXT[0], self.topic)) + (dump_tuple(get_theme().COLOR_INFORMATION_TEXT), self.topic)) self.text_win.refresh() self.input.refresh() return @@ -1083,10 +1089,10 @@ class MucTab(ChatTab): """ if not self.joined: return - color_visitor = get_theme().COLOR_USER_VISITOR[0] - color_other = get_theme().COLOR_USER_NONE[0] - color_moderator = get_theme().COLOR_USER_MODERATOR[0] - color_participant = get_theme().COLOR_USER_PARTICIPANT[0] + color_visitor = dump_tuple(get_theme().COLOR_USER_VISITOR) + color_other = dump_tuple(get_theme().COLOR_USER_NONE) + color_moderator = dump_tuple(get_theme().COLOR_USER_MODERATOR) + color_participant = dump_tuple(get_theme().COLOR_USER_PARTICIPANT) visitors, moderators, participants, others = [], [], [], [] aff = { 'owner': get_theme().CHAR_AFFILIATION_OWNER, @@ -1110,16 +1116,16 @@ class MucTab(ChatTab): buff = ['Users: %s \n' % len(self.users)] for moderator in moderators: buff.append('\x19%s}%s\x19o\x19%s}%s\x19o' % (color_moderator, - moderator[1], moderator[0].color[0], moderator[0].nick)) + moderator[1], dump_tuple(moderator[0].color), moderator[0].nick)) for participant in participants: buff.append('\x19%s}%s\x19o\x19%s}%s\x19o' % (color_participant, - participant[1], participant[0].color[0], participant[0].nick)) + participant[1], dump_tuple(participant[0].color), participant[0].nick)) for visitor in visitors: buff.append('\x19%s}%s\x19o\x19%s}%s\x19o' % (color_visitor, - visitor[1], visitor[0].color[0], visitor[0].nick)) + visitor[1], dump_tuple(visitor[0].color), visitor[0].nick)) for other in others: buff.append('\x19%s}%s\x19o\x19%s}%s\x19o' % (color_other, - other[1], other[0].color[0], other[0].nick)) + other[1], dump_tuple(other[0].color), other[0].nick)) buff.append('\n') message = ' '.join(buff) @@ -1434,13 +1440,19 @@ class MucTab(ChatTab): if self.core.current_tab() == self and self.core.status.show not in ('xa', 'away'): self.send_chat_state('active') new_user.color = get_theme().COLOR_OWN_NICK - self.add_message(_("\x19%(info_col)s}Your nickname is \x193}%(nick)s") % {'nick': from_nick, 'info_col': get_theme().COLOR_INFORMATION_TEXT[0]}) + self.add_message(_("\x19%(info_col)s}Your nickname is \x19%(nick_col)s}%(nick)s") % { + 'nick': from_nick, + 'nick_col': dump_tuple(new_user.color), + 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)}) if '201' in status_codes: - self.add_message('\x19%(info_col)s}Info: The room has been created' % {'info_col': get_theme().COLOR_INFORMATION_TEXT[0]}) + self.add_message('\x19%(info_col)s}Info: The room has been created' % { + 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)}) if '170' in status_codes: - self.add_message('\x191}Warning: \x19%(info_col)s}this room is publicly logged' % {'info_col': get_theme().COLOR_INFORMATION_TEXT[0]}) + self.add_message('\x191}Warning: \x19%(info_col)s}this room is publicly logged' % { + 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)}) if '100' in status_codes: - self.add_message('\x191}Warning: \x19%(info_col)s}This room is not anonymous.' % {'info_col': get_theme().COLOR_INFORMATION_TEXT[0]}) + self.add_message('\x191}Warning: \x19%(info_col)s}This room is not anonymous.' % { + 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)}) if self.core.current_tab() is not self: self.refresh_tab_win() self.core.current_tab().input.refresh() @@ -1491,12 +1503,14 @@ class MucTab(ChatTab): def on_non_member_kicked(self): """We have been kicked because the MUC is members-only""" - self.add_message('\x19%(info_col)s}%You have been kicked because you are not a member and the room is now members-only.' % {'info_col': get_theme().COLOR_INFORMATION_TEXT[0]}) + self.add_message('\x19%(info_col)s}%You have been kicked because you are not a member and the room is now members-only.' % { + 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)}) self.disconnect() def on_muc_shutdown(self): """We have been kicked because the MUC service is shutting down""" - self.add_message('\x19%(info_col)s}%You have been kicked because the MUC service is shutting down.' % {'info_col': get_theme().COLOR_INFORMATION_TEXT[0]}) + self.add_message('\x19%(info_col)s}%You have been kicked because the MUC service is shutting down.' % { + 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)}) self.disconnect() def on_user_join(self, from_nick, affiliation, show, status, role, jid): @@ -1508,11 +1522,16 @@ class MucTab(ChatTab): self.users.append(user) hide_exit_join = config.get_by_tabname('hide_exit_join', -1, self.general_jid, True) if hide_exit_join != 0: - color = user.color[0] if config.get_by_tabname('display_user_color_in_join_part', '', self.general_jid, True) == 'true' else 3 + color = dump_tuple(user.color) if config.get_by_tabname('display_user_color_in_join_part', '', self.general_jid, True) == 'true' else 3 if not jid.full: - msg = '\x194}%(spec)s \x19%(color)d}%(nick)s\x19%(info_col)s} joined the room' % {'nick':from_nick, 'color':color, 'spec':get_theme().CHAR_JOIN, 'info_col': get_theme().COLOR_INFORMATION_TEXT[0]} + msg = '\x194}%(spec)s \x19%(color)s}%(nick)s\x19%(info_col)s} joined the room' % { + 'nick':from_nick, 'color':color, 'spec':get_theme().CHAR_JOIN, + 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} else: - msg = '\x194}%(spec)s \x19%(color)d}%(nick)s \x19%(info_col)s}(\x194}%(jid)s\x19%(info_col)s}) joined the room' % {'spec':get_theme().CHAR_JOIN, 'nick':from_nick, 'color':color, 'jid':jid.full, 'info_col': get_theme().COLOR_INFORMATION_TEXT[0]} + msg = '\x194}%(spec)s \x19%(color)s}%(nick)s \x19%(info_col)s}(\x19%(jid_color)s}%(jid)s\x19%(info_col)s}) joined the room' % { + 'spec':get_theme().CHAR_JOIN, 'nick':from_nick, 'color':color, 'jid':jid.full, + 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT), + 'jid_color': dump_tuple(get_theme().COLOR_MUC_JID)} self.add_message(msg) self.core.on_user_rejoined_private_conversation(self.name, from_nick) @@ -1525,8 +1544,10 @@ class MucTab(ChatTab): if isinstance(_tab, PrivateTab) and safeJID(_tab.get_name()).bare == self.name: _tab.own_nick = new_nick user.change_nick(new_nick) - color = user.color[0] if config.get_by_tabname('display_user_color_in_join_part', '', self.general_jid, True) == 'true' else 3 - self.add_message('\x19%(color)d}%(old)s\x19%(info_col)s} is now known as \x19%(color)d}%(new)s' % {'old':from_nick, 'new':new_nick, 'color':color, 'info_col': get_theme().COLOR_INFORMATION_TEXT[0]}) + color = dump_tuple(user.color) if config.get_by_tabname('display_user_color_in_join_part', '', self.general_jid, True) == 'true' else 3 + self.add_message('\x19%(color)s}%(old)s\x19%(info_col)s} is now known as \x19%(color)s}%(new)s' % { + 'old':from_nick, 'new':new_nick, 'color':color, + 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)}) # rename the private tabs if needed self.core.rename_private_tabs(self.name, from_nick, new_nick) @@ -1540,9 +1561,13 @@ class MucTab(ChatTab): by = by.attrib['jid'] if by is not None else None if from_nick == self.own_nick: # we are banned if by: - kick_msg = _('\x191}%(spec)s \x193}You\x19%(info_col)s} have been banned by \x194}%(by)s') % {'spec': get_theme().CHAR_KICK, 'by':by, 'info_col': get_theme().COLOR_INFORMATION_TEXT[0]} + kick_msg = _('\x191}%(spec)s \x193}You\x19%(info_col)s} have been banned by \x194}%(by)s') % { + 'spec': get_theme().CHAR_KICK, 'by':by, + 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} else: - kick_msg = _('\x191}%(spec)s \x193}You\x19%(info_col)s} have been banned.') % {'spec':get_theme().CHAR_KICK, 'info_col': get_theme().COLOR_INFORMATION_TEXT[0]} + kick_msg = _('\x191}%(spec)s \x193}You\x19%(info_col)s} have been banned.') % { + 'spec': get_theme().CHAR_KICK, + 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} self.core.disable_private_tabs(self.name, reason=kick_msg) self.disconnect() self.refresh_tab_win() @@ -1562,13 +1587,18 @@ class MucTab(ChatTab): self.own_nick)) else: - color = user.color[0] if config.get_by_tabname('display_user_color_in_join_part', '', self.general_jid, True) == 'true' else 3 + color = dump_tuple(user.color) if config.get_by_tabname('display_user_color_in_join_part', '', self.general_jid, True) == 'true' else 3 if by: - kick_msg = _('\x191}%(spec)s \x19%(color)d}%(nick)s\x19%(info_col)s} has been banned by \x194}%(by)s') % {'spec':get_theme().CHAR_KICK, 'nick':from_nick, 'color':color, 'by':by, 'info_col': get_theme().COLOR_INFORMATION_TEXT[0]} + kick_msg = _('\x191}%(spec)s \x19%(color)s}%(nick)s\x19%(info_col)s} has been banned by \x194}%(by)s') % { + 'spec':get_theme().CHAR_KICK, 'nick':from_nick, 'color':color, 'by':by, + 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} else: - kick_msg = _('\x191}%(spec)s \x19%(color)d}%(nick)s\x19%(info_col)s} has been banned') % {'spec':get_theme().CHAR_KICK, 'nick':from_nick, 'color':color, 'info_col': get_theme().COLOR_INFORMATION_TEXT[0]} + kick_msg = _('\x191}%(spec)s \x19%(color)s}%(nick)s\x19%(info_col)s} has been banned') % { + 'spec':get_theme().CHAR_KICK, 'nick':from_nick, 'color':color, + 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} if reason is not None and reason.text: - kick_msg += _('\x19%(info_col)s} Reason: \x196}%(reason)s\x19%(info_col)s}') % {'reason': reason.text, 'info_col': get_theme().COLOR_INFORMATION_TEXT[0]} + kick_msg += _('\x19%(info_col)s} Reason: \x196}%(reason)s\x19%(info_col)s}') % { + 'reason': reason.text, 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} self._text_buffer.add_message(kick_msg) def on_user_kicked(self, presence, user, from_nick): @@ -1581,9 +1611,11 @@ class MucTab(ChatTab): by = by.attrib['jid'] if by is not None else None if from_nick == self.own_nick: # we are kicked if by: - kick_msg = _('\x191}%(spec)s \x193}You\x19%(info_col)s} have been kicked by \x193}%(by)s') % {'spec': get_theme().CHAR_KICK, 'by':by, 'info_col': get_theme().COLOR_INFORMATION_TEXT[0]} + kick_msg = _('\x191}%(spec)s \x193}You\x19%(info_col)s} have been kicked by \x193}%(by)s') % { + 'spec': get_theme().CHAR_KICK, 'by':by, + 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} else: - kick_msg = _('\x191}%(spec)s \x193}You\x19%(info_col)s} have been kicked.') % {'spec':get_theme().CHAR_KICK, 'info_col': get_theme().COLOR_INFORMATION_TEXT[0]} + kick_msg = _('\x191}%(spec)s \x193}You\x19%(info_col)s} have been kicked.') % {'spec':get_theme().CHAR_KICK, 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} self.core.disable_private_tabs(self.name, reason=kick_msg) self.disconnect() self.refresh_tab_win() @@ -1603,13 +1635,13 @@ class MucTab(ChatTab): self.name, self.own_nick)) else: - color = user.color[0] if config.get_by_tabname('display_user_color_in_join_part', '', self.general_jid, True) == 'true' else 3 + color = dump_tuple(user.color) if config.get_by_tabname('display_user_color_in_join_part', '', self.general_jid, True) == 'true' else 3 if by: - kick_msg = _('\x191}%(spec)s \x19%(color)d}%(nick)s\x19%(info_col)s} has been kicked by \x193}%(by)s') % {'spec':get_theme().CHAR_KICK, 'nick':from_nick, 'color':color, 'by':by, 'info_col': get_theme().COLOR_INFORMATION_TEXT[0]} + kick_msg = _('\x191}%(spec)s \x19%(color)s}%(nick)s\x19%(info_col)s} has been kicked by \x193}%(by)s') % {'spec': get_theme().CHAR_KICK, 'nick':from_nick, 'color':color, 'by':by, 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} else: - kick_msg = _('\x191}%(spec)s \x19%(color)d}%(nick)s\x19%(info_col)s} has been kicked') % {'spec':get_theme().CHAR_KICK, 'nick':from_nick, 'color':color, 'info_col': get_theme().COLOR_INFORMATION_TEXT[0]} + kick_msg = _('\x191}%(spec)s \x19%(color)s}%(nick)s\x19%(info_col)s} has been kicked') % {'spec': get_theme().CHAR_KICK, 'nick':from_nick, 'color':color, 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} if reason is not None and reason.text: - kick_msg += _('\x19%(info_col)s} Reason: \x196}%(reason)s') % {'reason': reason.text, 'info_col': get_theme().COLOR_INFORMATION_TEXT[0]} + kick_msg += _('\x19%(info_col)s} Reason: \x196}%(reason)s') % {'reason': reason.text, 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} self.add_message(kick_msg) def on_user_leave_groupchat(self, user, jid, status, from_nick, from_room): @@ -1626,11 +1658,11 @@ class MucTab(ChatTab): self.core.doupdate() hide_exit_join = config.get_by_tabname('hide_exit_join', -1, self.general_jid, True) if config.get_by_tabname('hide_exit_join', -1, self.general_jid, True) >= -1 else -1 if hide_exit_join == -1 or user.has_talked_since(hide_exit_join): - color = user.color[0] if config.get_by_tabname('display_user_color_in_join_part', '', self.general_jid, True) == 'true' else 3 + color = dump_tuple(user.color) if config.get_by_tabname('display_user_color_in_join_part', '', self.general_jid, True) == 'true' else 3 if not jid.full: - leave_msg = _('\x191}%(spec)s \x19%(color)d}%(nick)s\x19%(info_col)s} has left the room') % {'nick':from_nick, 'color':color, 'spec':get_theme().CHAR_QUIT, 'info_col': get_theme().COLOR_INFORMATION_TEXT[0]} + leave_msg = _('\x191}%(spec)s \x19%(color)s}%(nick)s\x19%(info_col)s} has left the room') % {'nick':from_nick, 'color':color, 'spec':get_theme().CHAR_QUIT, 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} else: - leave_msg = _('\x191}%(spec)s \x19%(color)d}%(nick)s\x19%(info_col)s} (\x194}%(jid)s\x19%(info_col)s}) has left the room') % {'spec':get_theme().CHAR_QUIT, 'nick':from_nick, 'color':color, 'jid':jid.full, 'info_col': get_theme().COLOR_INFORMATION_TEXT[0]} + leave_msg = _('\x191}%(spec)s \x19%(color)s}%(nick)s\x19%(info_col)s} (\x194}%(jid)s\x19%(info_col)s}) has left the room') % {'spec':get_theme().CHAR_QUIT, 'nick':from_nick, 'color':color, 'jid':jid.full, 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} if status: leave_msg += ' (%s)' % status self.add_message(leave_msg) @@ -1643,13 +1675,13 @@ class MucTab(ChatTab): # build the message display_message = False # flag to know if something significant enough # to be displayed has changed - color = user.color[0] if config.get_by_tabname('display_user_color_in_join_part', '', self.general_jid, True) == 'true' else 3 + color = dump_tuple(user.color) if config.get_by_tabname('display_user_color_in_join_part', '', self.general_jid, True) == 'true' else 3 if from_nick == self.own_nick: - msg = _('\x193}You\x19%(info_col)s} changed: ') % {'info_col': get_theme().COLOR_INFORMATION_TEXT[0]} + msg = _('\x193}You\x19%(info_col)s} changed: ') % {'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} else: - msg = _('\x19%(color)d}%(nick)s\x19%(info_col)s} changed: ') % {'nick': from_nick, 'color': color, 'info_col': get_theme().COLOR_INFORMATION_TEXT[0]} + msg = _('\x19%(color)s}%(nick)s\x19%(info_col)s} changed: ') % {'nick': from_nick, 'color': color, 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} if show not in SHOW_NAME: - self.core.information("%s from room %s sent an invalid show: %s" %\ + self.core.information(_("%s from room %s sent an invalid show: %s") %\ (from_nick, from_room, show), "Warning") if affiliation != user.affiliation: msg += _('affiliation: %s, ') % affiliation @@ -1772,7 +1804,7 @@ class MucTab(ChatTab): nick_color = nick_color or None highlight = False if (not nickname or time) and not txt.startswith('/me '): - txt = '\x19%(info_col)s}%(txt)s' % {'txt':txt, 'info_col': get_theme().COLOR_INFORMATION_TEXT[0]} + txt = '\x19%(info_col)s}%(txt)s' % {'txt':txt, 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)} else: # TODO highlight = self.do_highlight(txt, time, nickname) time = time or datetime.now() @@ -2031,7 +2063,7 @@ class PrivateTab(ChatTab): The user changed her nick in the corresponding muc: update the tab’s name and display a message. """ - self.add_message('\x193}%(old)s\x19%(info_col)s} is now known as \x193}%(new)s' % {'old':old_nick, 'new':new_nick, 'info_col': get_theme().COLOR_INFORMATION_TEXT[0]}) + self.add_message('\x193}%(old)s\x19%(info_col)s} is now known as \x193}%(new)s' % {'old':old_nick, 'new':new_nick, 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)}) new_jid = safeJID(self.name).bare+'/'+new_nick self.name = new_jid @@ -2042,9 +2074,9 @@ class PrivateTab(ChatTab): """ self.deactivate() if not status_message: - self.add_message(_('\x191}%(spec)s \x193}%(nick)s\x19%(info_col)s} has left the room') % {'nick':from_nick, 'spec':get_theme().CHAR_QUIT, 'info_col': get_theme().COLOR_INFORMATION_TEXT[0]}) + self.add_message(_('\x191}%(spec)s \x193}%(nick)s\x19%(info_col)s} has left the room') % {'nick':from_nick, 'spec':get_theme().CHAR_QUIT, 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)}) else: - self.add_message(_('\x191}%(spec)s \x193}%(nick)s\x19%(info_col)s} has left the room (%(status)s)"') % {'nick':from_nick, 'spec':get_theme().CHAR_QUIT, 'status': status_message, 'info_col': get_theme().COLOR_INFORMATION_TEXT[0]}) + self.add_message(_('\x191}%(spec)s \x193}%(nick)s\x19%(info_col)s} has left the room (%(status)s)"') % {'nick':from_nick, 'spec':get_theme().CHAR_QUIT, 'status': status_message, 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)}) return self.core.current_tab() is self @refresh_wrapper.conditional @@ -2058,8 +2090,8 @@ class PrivateTab(ChatTab): if tab and config.get_by_tabname('display_user_color_in_join_part', '', self.general_jid, True): user = tab.get_user_by_name(nick) if user: - color = user.color[0] - self.add_message('\x194}%(spec)s \x19%(color)d}%(nick)s\x19%(info_col)s} joined the room' % {'nick':nick, 'color': color, 'spec':get_theme().CHAR_JOIN, 'info_col': get_theme().COLOR_INFORMATION_TEXT[0]}) + color = dump_tuple(user.color) + self.add_message('\x194}%(spec)s \x19%(color)s}%(nick)s\x19%(info_col)s} joined the room' % {'nick':nick, 'color': color, 'spec':get_theme().CHAR_JOIN, 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)}) return self.core.current_tab() is self def activate(self, reason=None): @@ -2207,7 +2239,7 @@ class RosterInfoTab(Tab): if not tab: log.debug('Received message from nonexistent tab: %s', message['from']) message = '\x19%(info_col)s}Cannot send message to %(jid)s: contact blocked' % { - 'info_col': get_theme().COLOR_INFORMATION_TEXT[0], + 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT), 'jid': message['from'], } tab.add_message(message) @@ -3124,12 +3156,12 @@ class ConversationTab(ChatTab): msg = '\x19%s}The last activity of %s was %s ago%s' if not safeJID(from_).user: msg = '\x19%s}The uptime of %s is %s.' % ( - get_theme().COLOR_INFORMATION_TEXT[0], + dump_tuple(get_theme().COLOR_INFORMATION_TEXT), from_, common.parse_secs_to_str(seconds)) else: msg = '\x19%s}The last activity of %s was %s ago%s' % ( - get_theme().COLOR_INFORMATION_TEXT[0], + dump_tuple(get_theme().COLOR_INFORMATION_TEXT), from_, common.parse_secs_to_str(seconds), (' and his/her last status was %s' % status) if status else '',) @@ -3147,7 +3179,7 @@ class ConversationTab(ChatTab): else: resource = contact.get_highest_priority_resource() if resource: - self._text_buffer.add_message("\x19%(info_col)s}Status: %(status)s\x193}" % {'status': resource.status, 'info_col': get_theme().COLOR_INFORMATION_TEXT[0]}, None, None, None, None, None) + self._text_buffer.add_message("\x19%(info_col)s}Status: %(status)s\x193}" % {'status': resource.status, 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)}, None, None, None, None, None) return True def command_attention(self, message=''): diff --git a/src/theming.py b/src/theming.py index f7a0b431..c999ef2c 100644 --- a/src/theming.py +++ b/src/theming.py @@ -77,6 +77,41 @@ class Theme(object): needs. Create a new theme and share it if you think it can be useful for others. """ + @classmethod + def color_role(cls, role): + role_mapping = { + 'moderator': cls.COLOR_USER_MODERATOR, + 'participant': cls.COLOR_USER_PARTICIPANT, + 'visitor': cls.COLOR_USER_VISITOR, + 'none': cls.COLOR_USER_NONE, + '': cls.COLOR_USER_NONE + } + return role_mapping.get(role, cls.COLOR_USER_NONE) + + @classmethod + def char_affiliation(cls, affiliation): + affiliation_mapping = { + 'owner': cls.CHAR_AFFILIATION_OWNER, + 'admin': cls.CHAR_AFFILIATION_ADMIN, + 'member': cls.CHAR_AFFILIATION_MEMBER, + 'none': cls.CHAR_AFFILIATION_NONE + } + return affiliation_mapping.get(affiliation, cls.CHAR_AFFILIATION_NONE) + + @classmethod + def color_show(cls, show): + show_mapping = { + 'xa': cls.COLOR_STATUS_XA, + 'none': cls.COLOR_STATUS_NONE, + 'dnd': cls.COLOR_STATUS_DND, + 'away': cls.COLOR_STATUS_AWAY, + 'chat': cls.COLOR_STATUS_CHAT, + '': cls.COLOR_STATUS_ONLINE, + 'available': cls.COLOR_STATUS_ONLINE, + 'unavailable': cls.COLOR_STATUS_UNAVAILABLE, + } + return show_mapping.get(show, cls.COLOR_STATUS_NONE) + # Message text color COLOR_NORMAL_TEXT = (-1, -1) COLOR_INFORMATION_TEXT = (5, -1) # TODO @@ -89,6 +124,9 @@ class Theme(object): # fixed color if need be. COLOR_HIGHLIGHT_NICK = "reverse" + # Color of the participant JID in a MUC + COLOR_MUC_JID = (4, -1) + # User list color COLOR_USER_VISITOR = (239, -1) COLOR_USER_PARTICIPANT = (4, -1) @@ -266,6 +304,20 @@ def color_256_to_16(color): return color return table_256_to_16[color] +def dump_tuple(tup): + """ + Dump a tuple to a string of fg,bg,attr (optional) + """ + return ','.join(str(i) for i in tup) + +def read_tuple(_str): + """ + Read a tuple dumped with dump_tumple + """ + attrs = _str.split(',') + char = attrs[2] if len(attrs) > 2 else None + return (int(attrs[0]), int(attrs[1])), char + def to_curses_attr(color_tuple): """ Takes a color tuple (as defined at the top of this file) and diff --git a/src/windows.py b/src/windows.py index f10b1421..1bca14af 100644 --- a/src/windows.py +++ b/src/windows.py @@ -39,7 +39,7 @@ import wcwidth import singleton import collections -from theming import get_theme, to_curses_attr +from theming import get_theme, to_curses_attr, read_tuple, dump_tuple allowed_color_digits = ('0', '1', '2', '3', '4', '5', '6', '7') # msg is a reference to the corresponding Message tuple. text_start and text_end are the position @@ -168,7 +168,17 @@ class Win(object): self._win.attron(curses.A_BOLD) if attr_char in string.digits and attr_char != '': color_str = text[next_attr_char+1:text.find('}', next_attr_char)] - if color_str: + if ',' in color_str: + tup, char = read_tuple(color_str) + self._win.attron(to_curses_attr(tup)) + if char: + if char == 'o': + self._win.attrset(0) + elif char == 'u': + self._win.attron(curses.A_UNDERLINE) + elif char == 'b': + self._win.attron(curses.A_BOLD) + elif color_str: self._win.attron(to_curses_attr((int(color_str), -1))) text = text[next_attr_char+len(color_str)+2:] else: @@ -224,23 +234,7 @@ class UserList(Win): def __init__(self): Win.__init__(self) self.pos = 0 - self.color_role = {'moderator': lambda: get_theme().COLOR_USER_MODERATOR, - 'participant': lambda: get_theme().COLOR_USER_PARTICIPANT, - 'visitor': lambda: get_theme().COLOR_USER_VISITOR, - 'none': lambda: get_theme().COLOR_USER_NONE, - '': lambda: get_theme().COLOR_USER_NONE - } - self.symbol_affiliation = {'owner': lambda: get_theme().CHAR_AFFILIATION_OWNER, - 'admin': lambda: get_theme().CHAR_AFFILIATION_ADMIN, - 'member': lambda: get_theme().CHAR_AFFILIATION_MEMBER, - 'none': lambda: get_theme().CHAR_AFFILIATION_NONE, } - self.color_show = {'xa': lambda: get_theme().COLOR_STATUS_XA, - 'none': lambda: get_theme().COLOR_STATUS_NONE, - '': lambda: get_theme().COLOR_STATUS_NONE, - 'dnd': lambda: get_theme().COLOR_STATUS_DND, - 'away': lambda: get_theme().COLOR_STATUS_AWAY, - 'chat': lambda: get_theme().COLOR_STATUS_CHAT - } + def scroll_up(self): self.pos += self.height-1 return True @@ -297,18 +291,13 @@ class UserList(Win): self._refresh() def draw_role_affiliation(self, y, user): - if not user.role in self.color_role: - color = get_theme().COLOR_USER_NONE - else: - color = self.color_role[user.role]() - symbol = self.symbol_affiliation.get(user.affiliation, lambda: '-')() + theme = get_theme() + color = theme.color_role(user.role) + symbol = theme.char_affiliation(user.affiliation) self.addstr(y, 1, symbol, to_curses_attr(color)) def draw_status_chatstate(self, y, user): - if not user.show in self.color_show: - show_col = get_theme().COLOR_STATUS_NONE - else: - show_col = self.color_show[user.show]() + show_col = get_theme().color_show(user.show) if user.chatstate == 'composing': char = get_theme().CHAR_CHATSTATE_COMPOSING elif user.chatstate == 'active': @@ -505,15 +494,6 @@ class ConversationInfoWin(InfoWin): The line above the information window, displaying informations about the user we are talking to """ - color_show = {'xa': lambda: get_theme().COLOR_STATUS_XA, - 'none': lambda: get_theme().COLOR_STATUS_ONLINE, - '': lambda: get_theme().COLOR_STATUS_ONLINE, - 'available': lambda: get_theme().COLOR_STATUS_ONLINE, - 'dnd': lambda: get_theme().COLOR_STATUS_DND, - 'away': lambda: get_theme().COLOR_STATUS_AWAY, - 'chat': lambda: get_theme().COLOR_STATUS_CHAT, - 'unavailable': lambda: get_theme().COLOR_STATUS_UNAVAILABLE - } def __init__(self): InfoWin.__init__(self) @@ -563,7 +543,7 @@ class ConversationInfoWin(InfoWin): presence = "unavailable" else: presence = resource.presence - color = RosterWin.color_show[presence]() + color = get_theme().color_show(presence) self.addstr('[', to_curses_attr(get_theme().COLOR_INFORMATION_BAR)) self.addstr(get_theme().CHAR_STATUS, to_curses_attr(color)) self.addstr(']', to_curses_attr(get_theme().COLOR_INFORMATION_BAR)) @@ -1757,15 +1737,6 @@ class VerticalSeparator(Win): self.rewrite_line() class RosterWin(Win): - color_show = {'xa': lambda: get_theme().COLOR_STATUS_XA, - 'none': lambda: get_theme().COLOR_STATUS_ONLINE, - '': lambda: get_theme().COLOR_STATUS_ONLINE, - 'available': lambda: get_theme().COLOR_STATUS_ONLINE, - 'dnd':lambda: get_theme().COLOR_STATUS_DND, - 'away': lambda: get_theme().COLOR_STATUS_AWAY, - 'chat': lambda: get_theme().COLOR_STATUS_CHAT, - 'unavailable': lambda: get_theme().COLOR_STATUS_UNAVAILABLE - } def __init__(self): Win.__init__(self) @@ -1945,6 +1916,7 @@ class RosterWin(Win): the currently selected contact in the list """ + theme = get_theme() resource = contact.get_highest_priority_resource() if not resource: # There's no online resource @@ -1953,11 +1925,11 @@ class RosterWin(Win): else: presence = resource.presence nb = ' (%s)' % len(contact) - color = RosterWin.color_show[presence]() - added = 2 + len(get_theme().CHAR_STATUS) + len(nb) + color = theme.color_show(presence) + added = 2 + len(theme.CHAR_STATUS) + len(nb) self.addstr(y, 0, ' ') - self.addstr(get_theme().CHAR_STATUS, to_curses_attr(color)) + self.addstr(theme.CHAR_STATUS, to_curses_attr(color)) self.addstr(' ') if resource: @@ -2007,7 +1979,7 @@ class RosterWin(Win): """ Draw a specific resource line """ - color = RosterWin.color_show[resource.presence]() + color = get_theme().color_show(resource.presence) self.addstr(y, 4, get_theme().CHAR_STATUS, to_curses_attr(color)) if colored: self.addstr(y, 6, self.truncate_name(str(resource.jid), 6), to_curses_attr(get_theme().COLOR_SELECTED_ROW)) -- cgit v1.2.3