summaryrefslogtreecommitdiff
path: root/src/tabs.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/tabs.py')
-rw-r--r--src/tabs.py156
1 files changed, 64 insertions, 92 deletions
diff --git a/src/tabs.py b/src/tabs.py
index 24f347ba..88d8ad7f 100644
--- a/src/tabs.py
+++ b/src/tabs.py
@@ -13,13 +13,15 @@ Each Tab object has different refresh() and resize() methods, defining how its
Windows are displayed, resized, etc
"""
+MIN_WIDTH = 50
+MIN_HEIGHT = 22
+
import logging
log = logging.getLogger(__name__)
from gettext import gettext as _
import windows
-import theme
import curses
import difflib
import text_buffer
@@ -33,6 +35,8 @@ import timed_events
import multiuserchat as muc
+from theming import get_theme
+
from sleekxmpp.xmlstream.stanzabase import JID
from config import config
from roster import RosterGroup, roster
@@ -58,7 +62,7 @@ class Tab(object):
tab_core = None
def __init__(self):
self.input = None
- self._color_state = theme.COLOR_TAB_NORMAL
+ self._color_state = get_theme().COLOR_TAB_NORMAL
self.need_resize = False
self.nb = Tab.number
Tab.number += 1
@@ -86,7 +90,10 @@ class Tab(object):
@staticmethod
def resize(scr):
Tab.size = (Tab.height, Tab.width) = scr.getmaxyx()
- Tab.visible = True
+ if Tab.height < MIN_HEIGHT or Tab.width < MIN_WIDTH:
+ Tab.visible = False
+ else:
+ Tab.visible = True
def complete_commands(self, the_input):
"""
@@ -185,13 +192,13 @@ class Tab(object):
"""
called when this tab loses the focus.
"""
- self._color_state = theme.COLOR_TAB_NORMAL
+ self._color_state = get_theme().COLOR_TAB_NORMAL
def on_gain_focus(self):
"""
called when this tab gains the focus.
"""
- self._color_state = theme.COLOR_TAB_CURRENT
+ self._color_state = get_theme().COLOR_TAB_CURRENT
def add_message(self):
"""
@@ -467,9 +474,9 @@ class MucTab(ChatTab):
for user in users:
if user.nick == room.own_nick:
users.remove(user)
- nb_color = len(theme.LIST_COLOR_NICKNAMES)
+ nb_color = len(get_theme().LIST_COLOR_NICKNAMES)
for i, user in enumerate(sorted(users, key=compare_users, reverse=True)):
- user.color = theme.LIST_COLOR_NICKNAMES[i % nb_color]
+ user.color = get_theme().LIST_COLOR_NICKNAMES[i % nb_color]
self.text_win.rebuild_everything(self._room)
self.text_win.refresh(self._room)
self.input.refresh()
@@ -674,7 +681,6 @@ class MucTab(ChatTab):
"""
if not self.visible:
return
- self.need_resize = False
text_width = (self.width//10)*9
self.topic_win.resize(1, self.width, 0, 0)
self.v_separator.resize(self.height-3, 1, 1, 9*(self.width//10))
@@ -744,14 +750,14 @@ class MucTab(ChatTab):
return self._room
def on_lose_focus(self):
- self._room.set_color_state(theme.COLOR_TAB_NORMAL)
+ self._room.set_color_state(get_theme().COLOR_TAB_NORMAL)
self.text_win.remove_line_separator()
self.text_win.add_line_separator()
if config.get('send_chat_states', 'true') == 'true' and not self.input.get_text():
self.send_chat_state('inactive')
def on_gain_focus(self):
- self._room.set_color_state(theme.COLOR_TAB_CURRENT)
+ self._room.set_color_state(get_theme().COLOR_TAB_CURRENT)
if self.text_win.built_lines and self.text_win.built_lines[-1] is None:
self.text_win.remove_line_separator()
curses.curs_set(1)
@@ -794,10 +800,10 @@ class MucTab(ChatTab):
if from_nick == room.own_nick:
room.joined = True
self.send_chat_state('active')
- new_user.color = theme.COLOR_OWN_NICK
- room.add_message(_("\x195Your nickname is \x193%s") % (from_nick))
+ new_user.color = get_theme().COLOR_OWN_NICK
+ room.add_message(_("\x195}Your nickname is \x193}%s") % (from_nick))
if '170' in status_codes:
- room.add_message('\x191Warning: \x195this room is publicly logged')
+ room.add_message('\x191}Warning: \x195}this room is publicly logged')
else:
change_nick = '303' in status_codes
kick = '307' in status_codes and typ == 'unavailable'
@@ -836,9 +842,9 @@ class MucTab(ChatTab):
hide_exit_join = config.get('hide_exit_join', -1)
if hide_exit_join != 0:
if not jid.full:
- room.add_message('\x194%(spec)s \x193%(nick)s\x195 joined the room' % {'nick':from_nick, 'spec':theme.CHAR_JOIN})
+ room.add_message('\x194}%(spec)s \x193}%(nick)s\x195} joined the room' % {'nick':from_nick, 'spec':get_theme().CHAR_JOIN})
else:
- room.add_message('\x194%(spec)s \x193%(nick)s \x195(\x194%(jid)s\x195) joined the room' % {'spec':theme.CHAR_JOIN, 'nick':from_nick, 'jid':jid.full})
+ room.add_message('\x194}%(spec)s \x193}%(nick)s \x195}(\x194}%(jid)s\x195}) joined the room' % {'spec':get_theme().CHAR_JOIN, 'nick':from_nick, 'jid':jid.full})
self.core.on_user_rejoined_private_conversation(room.name, from_nick)
@@ -851,7 +857,7 @@ class MucTab(ChatTab):
if isinstance(_tab, PrivateTab) and JID(_tab.get_name()).bare == room.name:
_tab.get_room().own_nick = new_nick
user.change_nick(new_nick)
- room.add_message('\x193%(old)s\x195 is now known as \x193%(new)s' % {'old':from_nick, 'new':new_nick})
+ room.add_message('\x193}%(old)s\x195} is now known as \x193}%(new)s' % {'old':from_nick, 'new':new_nick})
# rename the private tabs if needed
self.core.rename_private_tabs(room.name, from_nick, new_nick)
@@ -869,16 +875,16 @@ class MucTab(ChatTab):
self.tab_win.refresh()
self.core.doupdate()
if by:
- kick_msg = _('\x191%(spec)s \x193You\x195 have been banned by \x194%(by)s') % {'spec': theme.CHAR_KICK, 'by':by}
+ kick_msg = _('\x191}%(spec)s \x193}You\x195} have been banned by \x194}%(by)s') % {'spec': get_theme().CHAR_KICK, 'by':by}
else:
- kick_msg = _('\x191%(spec)s \x193You\x195 have been banned.') % {'spec':theme.CHAR_KICK}
+ kick_msg = _('\x191}%(spec)s \x193}You\x195} have been banned.') % {'spec':get_theme().CHAR_KICK}
else:
if by:
- kick_msg = _('\x191%(spec)s \x193%(nick)s\x195 has been banned by \x194%(by)s') % {'spec':theme.CHAR_KICK, 'nick':from_nick, 'by':by}
+ kick_msg = _('\x191}%(spec)s \x193}%(nick)s\x195} has been banned by \x194}%(by)s') % {'spec':get_theme().CHAR_KICK, 'nick':from_nick, 'by':by}
else:
- kick_msg = _('\x191%(spec)s \x193%(nick)s\x195 has been banned') % {'spec':theme.CHAR_KICK, 'nick':from_nick.replace('"', '\\"')}
+ kick_msg = _('\x191}%(spec)s \x193}%(nick)s\x195 has been banned') % {'spec':get_theme().CHAR_KICK, 'nick':from_nick.replace('"', '\\"')}
if reason is not None and reason.text:
- kick_msg += _('\x195 Reason: \x196%(reason)s\x195') % {'reason': reason.text}
+ kick_msg += _('\x195} Reason: \x196}%(reason)s\x195}') % {'reason': reason.text}
room.add_message(kick_msg)
def on_user_kicked(self, room, presence, user, from_nick):
@@ -895,19 +901,19 @@ class MucTab(ChatTab):
self.tab_win.refresh()
self.core.doupdate()
if by:
- kick_msg = _('\x191%(spec)s \x193You\x195 have been kicked by \x193%(by)s') % {'spec': theme.CHAR_KICK, 'by':by}
+ kick_msg = _('\x191}%(spec)s \x193}You\x195} have been kicked by \x193}%(by)s') % {'spec': get_theme().CHAR_KICK, 'by':by}
else:
- kick_msg = _('\x191%(spec)s \x193You\x195 have been kicked.') % {'spec':theme.CHAR_KICK}
+ 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)
else:
if by:
- kick_msg = _('\x191%(spec)s \x193%(nick)s\x195 has been kicked by \x193%(by)s') % {'spec':theme.CHAR_KICK.replace('"', '\\"'), 'nick':from_nick.replace('"', '\\"'), 'by':by.replace('"', '\\"')}
+ kick_msg = _('\x191}%(spec)s \x193}%(nick)s\x195} has been kicked by \x193}%(by)s') % {'spec':get_theme().CHAR_KICK.replace('"', '\\"'), 'nick':from_nick.replace('"', '\\"'), 'by':by.replace('"', '\\"')}
else:
- kick_msg = _('\x191%(spec)s \x193%(nick)s\x195 has been kicked') % {'spec':theme.CHAR_KICK, 'nick':from_nick.replace('"', '\\"')}
+ kick_msg = _('\x191}%(spec)s \x193}%(nick)s\x195} has been kicked') % {'spec':get_theme().CHAR_KICK, 'nick':from_nick.replace('"', '\\"')}
if reason is not None and reason.text:
- kick_msg += _('\x195 Reason: \x196%(reason)s') % {'reason': reason.text}
+ kick_msg += _('\x195} Reason: \x196}%(reason)s') % {'reason': reason.text}
room.add_message(kick_msg)
def on_user_leave_groupchat(self, room, user, jid, status, from_nick, from_room):
@@ -924,9 +930,9 @@ class MucTab(ChatTab):
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 not jid.full:
- leave_msg = _('\x191%(spec)s \x193%(nick)s\x195 has left the room') % {'nick':from_nick, 'spec':theme.CHAR_QUIT}
+ leave_msg = _('\x191}%(spec)s \x193}%(nick)s\x195} has left the room') % {'nick':from_nick, 'spec':get_theme().CHAR_QUIT}
else:
- leave_msg = _('\x191%(spec)s \x193%(nick)s\x195 (\x194%(jid)s\x195) has left the room') % {'spec':theme.CHAR_QUIT, 'nick':from_nick, 'jid':jid.full}
+ leave_msg = _('\x191}%(spec)s \x193}%(nick)s\x195} (\x194}%(jid)s\x195}) has left the room') % {'spec':get_theme().CHAR_QUIT, 'nick':from_nick, 'jid':jid.full}
if status:
leave_msg += ' (%s)' % status
room.add_message(leave_msg)
@@ -940,7 +946,7 @@ class MucTab(ChatTab):
# build the message
display_message = False # flag to know if something significant enough
# to be displayed has changed
- msg = _('\x193%s\x195 changed: ')% from_nick.replace('"', '\\"')
+ msg = _('\x193}%s\x195} changed: ')% from_nick.replace('"', '\\"')
if show not in SHOW_NAME:
self.core.information("%s from room %s sent an invalid show: %s" %\
(from_nick, from_room, show), "warning")
@@ -993,12 +999,10 @@ class PrivateTab(ChatTab):
# keys
self.key_func['^I'] = self.completion
# commands
- self.commands['info'] = (self.command_info, _('Usage: /info\nInfo: Display some information about the user in the MUC: '), None)
+ #self.commands['info'] = (self.command_info, _('Usage: /info\nInfo: Display some information about the user in the MUC: '), None)
self.commands['unquery'] = (self.command_unquery, _("Usage: /unquery\nUnquery: close the tab"), None)
self.commands['part'] = (self.command_unquery, _("Usage: /part\nPart: 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.on = True
def completion(self):
@@ -1029,35 +1033,9 @@ class PrivateTab(ChatTab):
"""
self.core.close_tab()
- def command_version(self, arg):
- """
- /version
- """
- def callback(res):
- if not res:
- return self.core.information('Could not get the software version from %s' % (jid,), 'Warning')
- version = '%s is running %s version %s on %s' % (jid,
- res.get('name') or _('an unknown software'),
- res.get('version') or _('unknown'),
- res.get('os') or _('on an unknown platform'))
- self.core.information(version, 'Info')
- jid = self.get_room().name
- self.core.xmpp.plugin['xep_0092'].get_version(jid, callback=callback)
-
- def command_info(self, arg):
- """
- /info
- """
- if arg:
- self.parent_muc.command_info(arg)
- else:
- user = JID(self.get_room().name).resource
- self.parent_muc.command_info(user)
-
def resize(self):
if self.core.information_win_size >= self.height-3 or not self.visible:
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.info_header.resize(1, self.width, self.height-3-self.core.information_win_size, 0)
@@ -1078,10 +1056,10 @@ class PrivateTab(ChatTab):
self.input.refresh()
def get_color_state(self):
- if self._room.color_state == theme.COLOR_TAB_NORMAL or\
- self._room.color_state == theme.COLOR_TAB_CURRENT:
+ if self._room.color_state == get_theme().COLOR_TAB_NORMAL or\
+ self._room.color_state == get_theme().COLOR_TAB_CURRENT:
return self._room.color_state
- return theme.COLOR_TAB_PRIVATE
+ return get_theme().COLOR_TAB_PRIVATE
def set_color_state(self, color):
self._room.color_state = color
@@ -1103,14 +1081,14 @@ class PrivateTab(ChatTab):
return False
def on_lose_focus(self):
- self._room.set_color_state(theme.COLOR_TAB_NORMAL)
+ self._room.set_color_state(get_theme().COLOR_TAB_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():
self.send_chat_state('inactive')
def on_gain_focus(self):
- self._room.set_color_state(theme.COLOR_TAB_CURRENT)
+ self._room.set_color_state(get_theme().COLOR_TAB_CURRENT)
curses.curs_set(1)
if self.get_room().joined and config.get('send_chat_states', 'true') == 'true' and not self.input.get_text():
self.send_chat_state('active')
@@ -1146,24 +1124,22 @@ class PrivateTab(ChatTab):
"""
The user left the associated MUC
"""
- 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':theme.CHAR_QUIT.replace('"', '\\"')})
+ 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('"', '\\"')})
else:
- self.get_room().add_message(_('\x191%(spec)s \x193%(nick)s\x195 has left the room (%(status)s)"') % {'nick':from_nick.replace('"', '\\"'), 'spec':theme.CHAR_QUIT, 'status': status_message.replace('"', '\\"')})
- if self.core.current_tab() is self:
- self.refresh()
- self.core.doupdate()
+ 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.deactivate()
+ self.refresh()
+ self.core.doupdate()
def user_rejoined(self, nick):
"""
The user (or at least someone with the same nick) came back in the MUC
"""
+ self.get_room().add_message('\x194}%(spec)s \x193}%(nick)s\x195} joined the room' % {'nick':nick, 'spec':get_theme().CHAR_JOIN})
self.activate()
- self.get_room().add_message('\x194%(spec)s \x193%(nick)s\x195 joined the room' % {'nick':nick, 'spec':theme.CHAR_JOIN})
- if self.core.current_tab() is self:
- self.refresh()
- self.core.doupdate()
+ self.refresh()
+ self.core.doupdate()
def activate(self):
self.on = True
@@ -1185,7 +1161,7 @@ class RosterInfoTab(Tab):
self.contact_info_win = windows.ContactInfoWin()
self.default_help_message = windows.HelpText("Enter commands with “/”. “o”: toggle offline show")
self.input = self.default_help_message
- self.set_color_state(theme.COLOR_TAB_NORMAL)
+ self.set_color_state(get_theme().COLOR_TAB_NORMAL)
self.key_func['^I'] = self.completion
self.key_func[' '] = self.on_space
self.key_func["/"] = self.on_slash
@@ -1209,7 +1185,6 @@ class RosterInfoTab(Tab):
def resize(self):
if not self.visible:
return
- self.need_resize = False
roster_width = self.width//2
info_width = self.width-roster_width-1
self.v_separator.resize(self.height-2, 1, 0, roster_width)
@@ -1420,10 +1395,10 @@ class RosterInfoTab(Tab):
return self.reset_help_message()
def on_lose_focus(self):
- self._color_state = theme.COLOR_TAB_NORMAL
+ self._color_state = get_theme().COLOR_TAB_NORMAL
def on_gain_focus(self):
- self._color_state = theme.COLOR_TAB_CURRENT
+ self._color_state = get_theme().COLOR_TAB_CURRENT
if isinstance(self.input, windows.HelpText):
curses.curs_set(0)
else:
@@ -1526,7 +1501,7 @@ class ConversationTab(ChatTab):
def __init__(self, jid):
txt_buff = text_buffer.TextBuffer()
ChatTab.__init__(self, txt_buff)
- self.color_state = theme.COLOR_TAB_NORMAL
+ self.color_state = get_theme().COLOR_TAB_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)
@@ -1566,7 +1541,6 @@ class ConversationTab(ChatTab):
def resize(self):
if self.core.information_win_size >= self.height-3 or not self.visible:
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.upper_bar.resize(1, self.width, 0, 0)
@@ -1589,10 +1563,10 @@ class ConversationTab(ChatTab):
self.input.refresh()
def get_color_state(self):
- if self.color_state == theme.COLOR_TAB_NORMAL or\
- self.color_state == theme.COLOR_TAB_CURRENT:
+ if self.color_state == get_theme().COLOR_TAB_NORMAL or\
+ self.color_state == get_theme().COLOR_TAB_CURRENT:
return self.color_state
- return theme.COLOR_TAB_PRIVATE
+ return get_theme().COLOR_TAB_PRIVATE
def set_color_state(self, color):
self.color_state = color
@@ -1610,14 +1584,14 @@ class ConversationTab(ChatTab):
return False
def on_lose_focus(self):
- self.set_color_state(theme.COLOR_TAB_NORMAL)
+ self.set_color_state(get_theme().COLOR_TAB_NORMAL)
self.text_win.remove_line_separator()
self.text_win.add_line_separator()
if config.get('send_chat_states', 'true') == 'true' and not self.input.get_text() or not self.input.get_text().startswith('//'):
self.send_chat_state('inactive')
def on_gain_focus(self):
- self.set_color_state(theme.COLOR_TAB_CURRENT)
+ self.set_color_state(get_theme().COLOR_TAB_CURRENT)
curses.curs_set(1)
if config.get('send_chat_states', 'true') == 'true' and not self.input.get_text() or not self.input.get_text().startswith('//'):
self.send_chat_state('active')
@@ -1652,7 +1626,7 @@ class MucListTab(Tab):
"""
def __init__(self, server):
Tab.__init__(self)
- self._color_state = theme.COLOR_TAB_NORMAL
+ self._color_state = get_theme().COLOR_TAB_NORMAL
self.name = server
self.upper_message = windows.Topic()
self.upper_message.set_message('Chatroom list on server %s (Loading)' % self.name)
@@ -1684,7 +1658,6 @@ class MucListTab(Tab):
def resize(self):
if not self.visible:
return
- self.need_resize = False
self.upper_message.resize(1, self.width, 0, 0)
column_size = {'node-part': (self.width-5)//4,
'name': (self.width-5)//4*3,
@@ -1766,10 +1739,10 @@ class MucListTab(Tab):
return self.key_func[key]()
def on_lose_focus(self):
- self._color_state = theme.COLOR_TAB_NORMAL
+ self._color_state = get_theme().COLOR_TAB_NORMAL
def on_gain_focus(self):
- self._color_state = theme.COLOR_TAB_CURRENT
+ self._color_state = get_theme().COLOR_TAB_CURRENT
curses.curs_set(0)
def get_color_state(self):
@@ -1789,7 +1762,7 @@ class SimpleTextTab(Tab):
"""
def __init__(self, text):
Tab.__init__(self)
- self._color_state = theme.COLOR_TAB_NORMAL
+ self._color_state = get_theme().COLOR_TAB_NORMAL
self.text_win = windows.SimpleTextWin(text)
self.default_help_message = windows.HelpText("“Ctrl+q”: close")
self.input = self.default_help_message
@@ -1819,7 +1792,6 @@ class SimpleTextTab(Tab):
def resize(self):
if not self.visible:
return
- self.need_resize = False
self.text_win.resize(self.height-2, self.width, 0, 0)
self.input.resize(1, self.width, self.height-1, 0)
@@ -1832,10 +1804,10 @@ class SimpleTextTab(Tab):
self.input.refresh()
def on_lose_focus(self):
- self._color_state = theme.COLOR_TAB_NORMAL
+ self._color_state = get_theme().COLOR_TAB_NORMAL
def on_gain_focus(self):
- self._color_state = theme.COLOR_TAB_CURRENT
+ self._color_state = get_theme().COLOR_TAB_CURRENT
curses.curs_set(0)
def get_color_state(self):