summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gui.py60
-rw-r--r--src/room.py31
-rw-r--r--src/theme.py131
-rw-r--r--src/user.py7
-rw-r--r--src/window.py87
5 files changed, 225 insertions, 91 deletions
diff --git a/src/gui.py b/src/gui.py
index 8038243f..e59a97b0 100644
--- a/src/gui.py
+++ b/src/gui.py
@@ -31,6 +31,7 @@ import webbrowser
from datetime import datetime
import common
+import theme
from handler import Handler
from config import config
@@ -98,6 +99,7 @@ class Gui(object):
'nick': (self.command_nick, _("Usage: /nick <nickname>\nNick: Change your nickname in the current room")),
'say': (self.command_say, _('Usage: /say <message>\nSay: Just send the message. Useful if you want your message to begin with a "/"')),
'whois': (self.command_whois, _('Usage: /whois <nickname>\nWhois: Request many informations about the user.')),
+ 'theme': (self.command_theme, _('Usage: /theme\nTheme: Reload the theme defined in the config file.')),
}
self.key_func = {
@@ -193,35 +195,10 @@ class Gui(object):
"""
ncurses initialization
"""
- curses.start_color()
+ theme.init_colors()
curses.noecho()
curses.curs_set(0)
- curses.use_default_colors()
stdscr.keypad(True)
- curses.init_pair(1, curses.COLOR_WHITE,
- curses.COLOR_BLUE)
- curses.init_pair(2, curses.COLOR_WHITE, -1) # Visitor
- curses.init_pair(3, curses.COLOR_CYAN, -1)
- curses.init_pair(4, curses.COLOR_RED, -1) # Admin
- curses.init_pair(5, curses.COLOR_BLUE, -1) # Participant
- curses.init_pair(6, curses.COLOR_CYAN, -1)
- curses.init_pair(7, curses.COLOR_GREEN, -1)
- curses.init_pair(8, curses.COLOR_MAGENTA, -1)
- curses.init_pair(9, curses.COLOR_YELLOW, -1)
- curses.init_pair(10, curses.COLOR_WHITE,
- curses.COLOR_CYAN) # current room
- curses.init_pair(11, curses.COLOR_WHITE,
- curses.COLOR_BLUE) # normal room
- curses.init_pair(12, curses.COLOR_WHITE,
- curses.COLOR_MAGENTA) # new message room
- curses.init_pair(13, curses.COLOR_WHITE,
- curses.COLOR_RED) # highlight room
- curses.init_pair(14, curses.COLOR_WHITE,
- curses.COLOR_YELLOW)
- curses.init_pair(15, curses.COLOR_WHITE, # new message in private room
- curses.COLOR_GREEN)
- curses.init_pair(16, curses.COLOR_YELLOW,
- curses.COLOR_BLUE)
def reset_curses(self):
"""
@@ -243,7 +220,7 @@ class Gui(object):
"""
Refresh everything
"""
- self.current_room().set_color_state(common.ROOM_STATE_CURRENT)
+ self.current_room().set_color_state(theme.COLOR_TAB_CURRENT)
self.window.refresh(self.rooms)
def join_room(self, room, nick):
@@ -251,7 +228,7 @@ class Gui(object):
join the specified room (muc), using the specified nick
"""
r = Room(room, nick, self.window)
- self.current_room().set_color_state(11)
+ self.current_room().set_color_state(theme.COLOR_TAB_NORMAL)
if self.current_room().nb == 0:
self.rooms.append(r)
else:
@@ -305,15 +282,15 @@ class Gui(object):
- A Muc with any new message
"""
for room in self.rooms:
- if room.color_state == 15:
+ if room.color_state == theme.COLOR_TAB_PRIVATE:
self.command_win('%s' % room.nb)
return
for room in self.rooms:
- if room.color_state == 13:
+ if room.color_state == theme.COLOR_TAB_HIGHLIGHT:
self.command_win('%s' % room.nb)
return
for room in self.rooms:
- if room.color_state == 12:
+ if room.color_state == theme.COLOR_TAB_NEW_MESSAGE:
self.command_win('%s' % room.nb)
return
@@ -321,20 +298,20 @@ class Gui(object):
"""
rotate the rooms list to the right
"""
- self.current_room().set_color_state(common.ROOM_STATE_NONE)
+ self.current_room().set_color_state(theme.COLOR_TAB_NORMAL)
self.current_room().remove_line_separator()
self.rooms.append(self.rooms.pop(0))
- self.current_room().set_color_state(common.ROOM_STATE_CURRENT)
+ self.current_room().set_color_state(theme.COLOR_TAB_CURRENT)
self.refresh_window()
def rotate_rooms_left(self, args=None):
"""
rotate the rooms list to the right
"""
- self.current_room().set_color_state(common.ROOM_STATE_NONE)
+ self.current_room().set_color_state(theme.COLOR_TAB_NORMAL)
self.current_room().remove_line_separator()
self.rooms.insert(0, self.rooms.pop())
- self.current_room().set_color_state(common.ROOM_STATE_CURRENT)
+ self.current_room().set_color_state(theme.COLOR_TAB_CURRENT)
self.refresh_window()
def scroll_page_down(self, args=None):
@@ -495,7 +472,7 @@ class Gui(object):
for child in xtag.getTags('status'):
if child.getAttr('code') == '170':
self.add_message_to_room(room, 'Warning: this room is publicly logged')
- new_user.color = 2
+ new_user.color = theme.COLOR_OWN_NICK
else:
change_nick = stanza.getStatusCode() == '303'
kick = stanza.getStatusCode() == '307'
@@ -674,6 +651,11 @@ class Gui(object):
nickname = args[0]
self.muc.request_vcard(room.name, nickname)
+ def command_theme(self, arg):
+ """
+ """
+ theme.reload_theme()
+
def command_win(self, arg):
"""
/win <number>
@@ -689,17 +671,17 @@ class Gui(object):
return
if self.current_room().nb == nb:
return
- self.current_room().set_color_state(common.ROOM_STATE_NONE)
+ self.current_room().set_color_state(theme.COLOR_TAB_NORMAL)
self.current_room().remove_line_separator()
start = self.current_room()
self.rooms.append(self.rooms.pop(0))
while self.current_room().nb != nb:
self.rooms.append(self.rooms.pop(0))
if self.current_room() == start:
- self.current_room().set_color_state(common.ROOM_STATE_CURRENT)
+ self.current_room().set_color_state(theme.COLOR_TAB_CURRENT)
self.refresh_window()
return
- self.current_room().set_color_state(common.ROOM_STATE_CURRENT)
+ self.current_room().set_color_state(theme.COLOR_TAB_CURRENT)
self.refresh_window()
def command_kick(self, arg):
diff --git a/src/room.py b/src/room.py
index 63003229..391f6f79 100644
--- a/src/room.py
+++ b/src/room.py
@@ -23,6 +23,7 @@ from logging import logger
from message import Message
import common
+import theme
class Room(object):
"""
@@ -32,7 +33,7 @@ class Room(object):
self.jid = jid # used for a private chat. None if it's a MUC
self.name = name
self.own_nick = nick
- self.color_state = common.ROOM_STATE_NONE # color used in RoomInfo
+ self.color_state = theme.COLOR_TAB_NORMAL # color used in RoomInfo
self.nb = Room.number # number used in RoomInfo
Room.number += 1
self.joined = False # false until self presence is received
@@ -68,25 +69,25 @@ class Room(object):
"""
Set the tab color and returns the txt color
"""
- color = None
+ color = theme.COLOR_NORMAL_TEXT
if not time and nickname and nickname.encode('utf-8') != self.own_nick and self.joined: # do the highlight
try:
if self.own_nick in txt.encode('utf-8'):
- self.set_color_state(common.ROOM_STATE_HL)
- color = 4
+ self.set_color_state(theme.COLOR_TAB_HIGHLIGHT)
+ color = theme.COLOR_HIGHLIGHT_TEXT
except UnicodeDecodeError:
try:
if self.own_nick in txt:
- self.set_color_state(common.ROOM_STATE_HL)
- color = 4
+ self.set_color_state(theme.COLOR_TAB_HIGHLIGHT)
+ color = theme.COLOR_HIGHLIGHT_TEXT
except:
pass
else:
highlight_words = config.get('highlight_on', '').split(':')
for word in highlight_words:
if word.lower() in txt.lower() and word != '':
- self.set_color_state(common.ROOM_STATE_HL)
- color = 4
+ self.set_color_state(theme.COLOR_TAB_HIGHLIGHT)
+ color = theme.COLOR_HIGHLIGHT_TEXT
break
return color
@@ -100,20 +101,20 @@ class Room(object):
user = self.get_user_by_name(nickname) if nickname is not None else None
if user:
user.set_last_talked(datetime.now())
- color = None
+ color = theme.COLOR_NORMAL_TEXT
if not time and nickname and\
nickname != self.own_nick and\
- self.color_state != common.ROOM_STATE_CURRENT:
- if not self.jid and self.color_state != common.ROOM_STATE_HL:
- self.set_color_state(common.ROOM_STATE_MESSAGE)
+ self.color_state != theme.COLOR_TAB_CURRENT:
+ if not self.jid and self.color_state != theme.COLOR_TAB_HIGHLIGHT:
+ self.set_color_state(theme.COLOR_TAB_NEW_MESSAGE)
elif self.jid:
- self.set_color_state(common.ROOM_STATE_PRIVATE)
+ self.set_color_state(theme.COLOR_TAB_PRIVATE)
if not nickname:
- color = 8
+ color = theme.COLOR_INFORMATION_TEXT
else:
color = self.do_highlight(txt, time, nickname)
if time: # History messages are colored to be distinguished
- color = 8
+ color = theme.COLOR_INFORMATION_TEXT
time = time if time is not None else datetime.now()
self.messages.append(Message(txt, time, nickname, user, color))
diff --git a/src/theme.py b/src/theme.py
new file mode 100644
index 00000000..1748e4a3
--- /dev/null
+++ b/src/theme.py
@@ -0,0 +1,131 @@
+# -*- coding:utf-8 -*-
+#
+# Copyright 2010 Le Coz Florent <louizatakk@fedoraproject.org>
+#
+# This file is part of Poezio.
+#
+# Poezio is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, version 3 of the License.
+#
+# Poezio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Poezio. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Define the variables (colors and some other stuff) that are
+used when drawing the interface (mainly colors)
+"""
+
+import curses
+import inspect
+import imp
+from config import config
+
+## Define the default colors
+## Do not change these colors, create a theme file instead.
+
+# Message text color
+COLOR_NORMAL_TEXT = 0
+COLOR_INFORMATION_TEXT = 76
+COLOR_HIGHLIGHT_TEXT = 77
+
+# User list color
+COLOR_USER_VISITOR = 78
+COLOR_USER_PARTICIPANT = 73
+COLOR_USER_NONE = 80
+COLOR_USER_MODERATOR = 77
+
+# Separators
+COLOR_VERTICAL_SEPARATOR = 73
+COLOR_NEW_TEXT_SEPARATOR = 75
+
+# Time
+COLOR_TIME_SEPARATOR = 79
+COLOR_TIME_BRACKETS = 74
+COLOR_TIME_NUMBERS = 0
+
+# Tabs
+COLOR_TAB_NORMAL = 15
+COLOR_TAB_CURRENT = 24
+COLOR_TAB_NEW_MESSAGE = 42
+COLOR_TAB_HIGHLIGHT = 51
+COLOR_TAB_PRIVATE = 33
+
+# Nickname colors
+LIST_COLOR_NICKNAMES = [
+ 73, 74, 75, 76, 77, 78, 79
+ ]
+COLOR_OWN_NICK = 72
+
+# Status color
+COLOR_STATUS_XA = 40
+COLOR_STATUS_NONE = 0
+COLOR_STATUS_DND = 50
+COLOR_STATUS_AWAY = 70
+COLOR_STATUS_CHAT = 30
+
+# Bars
+COLOR_INFORMATION_BAR = 15
+COLOR_TOPIC_BAR = 15
+COLOR_PRIVATE_ROOM_BAR = 33
+COLOR_SCROLLABLE_NUMBER = 16
+
+def init_colors():
+ """
+ Initilization of all the available ncurses colors
+ """
+ curses.start_color()
+ curses.use_default_colors()
+ colors_list = [
+ curses.COLOR_BLACK,
+ curses.COLOR_BLUE,
+ curses.COLOR_CYAN,
+ curses.COLOR_GREEN,
+ curses.COLOR_MAGENTA,
+ curses.COLOR_RED,
+ curses.COLOR_WHITE,
+ curses.COLOR_YELLOW,
+ -1
+ ]
+ cpt = 0
+ for i in colors_list:
+ for y in colors_list:
+ curses.init_pair(cpt, y, i)
+ cpt += 1
+ reload_theme()
+
+def reload_theme():
+ current_module = __import__(inspect.getmodulename(__file__))
+ path = config.get('theme_file', '../default.theme')
+ try:
+ theme = imp.load_source('theme', path)
+ except:
+ return
+ for var in dir(theme):
+ if var.startswith('COLOR_'):
+ globals()[var] = getattr(theme, var)
+
+if __name__ == '__main__':
+ """
+ Launch 'python theme.py' to see the list of all the available colors
+ in your terminal
+ """
+ s = curses.initscr()
+ curses.start_color()
+ curses.use_default_colors()
+ for i in xrange(80):
+ s.attron(curses.color_pair(i))
+ s.addstr(str(i))
+ s.attroff(curses.color_pair(i))
+ s.addstr(' ')
+ s.refresh()
+ s.getch()
+ s.endwin()
+
+
+
diff --git a/src/user.py b/src/user.py
index 5dbe77ce..2959a76c 100644
--- a/src/user.py
+++ b/src/user.py
@@ -16,10 +16,11 @@
# You should have received a copy of the GNU General Public License
# along with Poezio. If not, see <http://www.gnu.org/licenses/>.
-from random import randrange
+from random import randrange, choice
from config import config
from datetime import timedelta, datetime
import curses
+import theme
class User(object):
"""
@@ -29,7 +30,7 @@ class User(object):
self.last_talked = None
self.update(affiliation, show, status, role)
self.change_nick(nick)
- self.color = randrange(3, 10) # assign a random color
+ self.color = choice(theme.LIST_COLOR_NICKNAMES)
def update(self, affiliation, show, status, role):
self.affiliation = affiliation
@@ -60,5 +61,3 @@ class User(object):
def __repr__(self):
return ">%s<" % (self.nick.decode('utf-8'))
- # return "<user.User object nick:%s show:%s(%s) status:%s affiliation:%s>"\
- # % (self.nick.decode('utf-8'), self.show, type(self.show), self.status, self.affiliation)
diff --git a/src/window.py b/src/window.py
index 6aa44899..584f2f8b 100644
--- a/src/window.py
+++ b/src/window.py
@@ -29,6 +29,7 @@ from config import config
from threading import Lock
from message import Line
+import theme
g_lock = Lock()
@@ -59,16 +60,16 @@ class UserList(Win):
def __init__(self, height, width, y, x, parent_win, visible):
Win.__init__(self, height, width, y, x, parent_win)
self.visible = visible
- self.color_role = {'moderator': 4,
- 'participant':5,
- 'visitor':2,
- 'none':3
+ self.color_role = {'moderator': theme.COLOR_USER_MODERATOR,
+ 'participant':theme.COLOR_USER_PARTICIPANT,
+ 'visitor':theme.COLOR_USER_VISITOR,
+ 'none':theme.COLOR_USER_NONE
}
- self.color_show = {'xa':12,
- 'None':8,
- 'dnd':13,
- 'away':14,
- 'chat':15
+ self.color_show = {'xa':theme.COLOR_STATUS_XA,
+ 'None':theme.COLOR_STATUS_NONE,
+ 'dnd':theme.COLOR_STATUS_DND,
+ 'away':theme.COLOR_STATUS_AWAY,
+ 'chat':theme.COLOR_STATUS_CHAT
}
def refresh(self, users):
@@ -95,11 +96,11 @@ class UserList(Win):
try:
role_col = self.color_role[user.role]
except KeyError:
- role_col = 5
+ role_col = theme.COLOR_USER_NONE
try:
show_col = self.color_show[user.show]
except KeyError:
- show_col = 8
+ show_col = theme.COLOR_STATUS_NONE
self.win.attron(curses.color_pair(show_col))
self.win.addnstr(y, 0, " ", 1)
self.win.attroff(curses.color_pair(show_col))
@@ -136,10 +137,10 @@ class Topic(Win):
self.win.erase()
if not jid:
try:
- self.win.addstr(0, 0, topic, curses.color_pair(1))
+ self.win.addstr(0, 0, topic, curses.color_pair(theme.COLOR_TOPIC_BAR))
while True:
try:
- self.win.addch(' ', curses.color_pair(1))
+ self.win.addch(' ', curses.color_pair(theme.COLOR_TOPIC_BAR))
except:
break
except:
@@ -149,7 +150,7 @@ class Topic(Win):
nick = '/'.join(jid.split('/')[1:])
topic = _('%(nick)s from room %(room)s' % {'nick': nick, 'room':room})
self.win.addnstr(0, 0, topic.encode('utf-8') + " "*(self.width-len(topic)), self.width-1
- , curses.color_pair(15))
+ , curses.color_pair(theme.COLOR_PRIVATE_ROOM_BAR))
self.win.refresh()
g_lock.release()
@@ -169,7 +170,7 @@ class RoomInfo(Win):
down
"""
if current_room.pos > 0:
- self.win.addstr(' -PLUS(%s)-' % current_room.pos, curses.color_pair(16) | curses.A_BOLD)
+ self.win.addstr(' -PLUS(%s)-' % current_room.pos, curses.color_pair(theme.COLOR_SCROLLABLE_NUMBER) | curses.A_BOLD)
def refresh(self, rooms, current):
if not self.visible:
@@ -179,28 +180,28 @@ class RoomInfo(Win):
g_lock.acquire()
self.win.erase()
self.win.addnstr(0, 0, "[", self.width
- ,curses.color_pair(1))
+ ,curses.color_pair(theme.COLOR_INFORMATION_BAR))
sorted_rooms = sorted(rooms, compare_room)
for room in sorted_rooms:
color = room.color_state
try:
self.win.addstr("%s" % str(room.nb), curses.color_pair(color))
- self.win.addstr(u"|".encode('utf-8'), curses.color_pair(1))
+ self.win.addstr(u"|".encode('utf-8'), curses.color_pair(theme.COLOR_INFORMATION_BAR))
except: # end of line
break
(y, x) = self.win.getyx()
try:
- self.win.addstr(y, x-1, '] '+ current.name, curses.color_pair(1))
+ self.win.addstr(y, x-1, '] '+ current.name, curses.color_pair(theme.COLOR_INFORMATION_BAR))
except:
try:
- self.win.addstr(y, x-1, '] '+ current.name.encode('utf-8'), curses.color_pair(1))
+ self.win.addstr(y, x-1, '] '+ current.name.encode('utf-8'), curses.color_pair(theme.COLOR_INFORMATION_BAR))
except:
pass
pass
self.print_scroll_position(current)
while True:
try:
- self.win.addstr(' ', curses.color_pair(1))
+ self.win.addstr(' ', curses.color_pair(theme.COLOR_INFORMATION_BAR))
except:
break
self.win.refresh()
@@ -315,9 +316,9 @@ class TextWin(Win):
def write_line_separator(self):
"""
"""
- self.win.attron(curses.color_pair(7))
+ self.win.attron(curses.color_pair(theme.COLOR_NEW_TEXT_SEPARATOR))
self.win.addstr(' -'*(self.width/2))
- self.win.attroff(curses.color_pair(7))
+ self.win.attroff(curses.color_pair(theme.COLOR_NEW_TEXT_SEPARATOR))
def write_text(self, y, x, txt, color):
"""
@@ -349,15 +350,35 @@ class TextWin(Win):
"""
Write the date on the yth line of the window
"""
- self.win.addnstr('['+time.strftime("%H"), 3)
- self.win.attron(curses.color_pair(9))
+ self.win.attron(curses.color_pair(theme.COLOR_TIME_BRACKETS))
+ self.win.addnstr('[', 1)
+ self.win.attroff(curses.color_pair(theme.COLOR_TIME_BRACKETS))
+
+ self.win.attron(curses.color_pair(theme.COLOR_TIME_NUMBERS))
+ self.win.addnstr(time.strftime("%H"), 2)
+ self.win.attroff(curses.color_pair(theme.COLOR_TIME_NUMBERS))
+
+ self.win.attron(curses.color_pair(theme.COLOR_TIME_SEPARATOR))
self.win.addnstr(':', 1)
- self.win.attroff(curses.color_pair(9))
- self.win.addnstr(time.strftime('%M'), 2)
- self.win.attron(curses.color_pair(9))
+ self.win.attroff(curses.color_pair(theme.COLOR_TIME_SEPARATOR))
+
+ self.win.attron(curses.color_pair(theme.COLOR_TIME_NUMBERS))
+ self.win.addnstr(time.strftime("%M"), 2)
+ self.win.attroff(curses.color_pair(theme.COLOR_TIME_NUMBERS))
+
+ self.win.attron(curses.color_pair(theme.COLOR_TIME_SEPARATOR))
self.win.addnstr(':', 1)
- self.win.attroff(curses.color_pair(9))
- self.win.addnstr(time.strftime('%S') + "] ", 4)
+ self.win.attroff(curses.color_pair(theme.COLOR_TIME_SEPARATOR))
+
+ self.win.attron(curses.color_pair(theme.COLOR_TIME_NUMBERS))
+ self.win.addnstr(time.strftime('%S'), 2)
+ self.win.attroff(curses.color_pair(theme.COLOR_TIME_NUMBERS))
+
+ self.win.attron(curses.color_pair(theme.COLOR_TIME_BRACKETS))
+ self.win.addstr(']')
+ self.win.attroff(curses.color_pair(theme.COLOR_TIME_BRACKETS))
+
+ self.win.addstr(' ')
def resize(self, height, width, y, x, stdscr, visible):
self.visible = visible
@@ -726,9 +747,9 @@ class Window(object):
else:
visible = True
if visible:
- stdscr.attron(curses.color_pair(5))
+ stdscr.attron(curses.color_pair(theme.COLOR_VERTICAL_SEPARATOR))
stdscr.vline(1, 9*(self.width/10), curses.ACS_VLINE, self.height-2)
- stdscr.attroff(curses.color_pair(5))
+ stdscr.attroff(curses.color_pair(theme.COLOR_VERTICAL_SEPARATOR))
self.user_win = UserList(self.height-3, (self.width/10)-1, 1, 9*(self.width/10)+1, stdscr, visible)
self.topic_win = Topic(1, self.width, 0, 0, stdscr, visible)
self.info_win = RoomInfo(1, self.width, self.height-2, 0, stdscr, visible)
@@ -745,9 +766,9 @@ class Window(object):
else:
visible = True
if visible:
- stdscr.attron(curses.color_pair(5))
+ stdscr.attron(curses.color_pair(theme.COLOR_VERTICAL_SEPARATOR))
stdscr.vline(1, 9*(self.width/10), curses.ACS_VLINE, self.height-2)
- stdscr.attroff(curses.color_pair(5))
+ stdscr.attroff(curses.color_pair(theme.COLOR_VERTICAL_SEPARATOR))
text_width = (self.width/10)*9;
self.topic_win.resize(1, self.width, 0, 0, stdscr, visible)
self.info_win.resize(1, self.width, self.height-2, 0, stdscr, visible)