Commit 26ea842c authored by mathieui's avatar mathieui

Add a way to format background colors in a string

(also add colors to the /info command in MUCs)
parent 545e67c5
......@@ -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():
......
This diff is collapsed.
......@@ -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
......
......@@ -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))
......
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