summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core.py11
-rw-r--r--src/data_forms.py69
-rw-r--r--src/plugin_manager.py2
-rw-r--r--src/tabs.py59
4 files changed, 101 insertions, 40 deletions
diff --git a/src/core.py b/src/core.py
index 1f60e252..0e09cf04 100644
--- a/src/core.py
+++ b/src/core.py
@@ -128,9 +128,8 @@ class Core(object):
'connect': (self.command_reconnect, _('Usage: /connect\nConnect: disconnect from the remote server if you are currently connected and then connect to it again'), None),
'server_cycle': (self.command_server_cycle, _('Usage: /server_cycle [domain] [message]\nServer Cycle: disconnect and reconnects in all the rooms in domain.'), None),
'bind': (self.command_bind, _('Usage: /bind <key> <equ>\nBind: bind a key to an other key or to a “command”. For example "/bind ^H KEY_UP" makes Control + h do the same same than the Up key.'), None),
- 'pubsub': (self.command_pubsub, _('Usage: /pubsub <domain>\nPubsub: Open a pubsub browser on the given domain'), None),
- 'load': (self.command_load, _('Usage: /load <script.py>\nLoad: Load the specified python script'), self.plugin_manager.completion_load),
- 'unload': (self.command_unload, _('Usage: /unload <script.py>\nUnload: Unload the specified python script'), self.plugin_manager.completion_unload),
+ 'load': (self.command_load, _('Usage: /load <plugin>\nLoad: Load the specified plugin'), self.plugin_manager.completion_load),
+ 'unload': (self.command_unload, _('Usage: /unload <plugin>\nUnload: Unload the specified plugin'), self.plugin_manager.completion_unload),
}
self.key_func = {
@@ -1137,7 +1136,7 @@ class Core(object):
def command_load(self, arg):
"""
- /load <script.py>
+ /load <plugin>
"""
args = arg.split()
if len(args) != 1:
@@ -1148,7 +1147,7 @@ class Core(object):
def command_unload(self, arg):
"""
- /unload <script.py>
+ /unload <plugin>
"""
args = arg.split()
if len(args) != 1:
@@ -1308,7 +1307,7 @@ class Core(object):
t = self.current_tab()
if not isinstance(t, tabs.MucTab) and not isinstance(t, tabs.PrivateTab):
return
- room = t.get_name()
+ room = JID(t.get_name()).bare
nick = t.get_room().own_nick
else:
info = JID(args[0])
diff --git a/src/data_forms.py b/src/data_forms.py
index 9510bdf8..99d08caa 100644
--- a/src/data_forms.py
+++ b/src/data_forms.py
@@ -16,6 +16,7 @@ import curses
from windows import g_lock
import windows
from tabs import Tab
+from theming import to_curses_attr, get_theme
class DataFormsTab(Tab):
"""
@@ -85,7 +86,7 @@ class FieldInput(object):
"""
def __init__(self, field):
self._field = field
- self.color = 14
+ self.color = (14, -1)
def set_color(self, color):
self.color = color
@@ -113,6 +114,27 @@ class FieldInput(object):
"""
return ''
+class ColoredLabel(windows.Win):
+ def __init__(self, text):
+ self.text = text
+ self.color = get_theme().COLOR_NORMAL_TEXT
+ windows.Win.__init__(self)
+
+ def resize(self, height, width, y, x):
+ self._resize(height, width, y, x)
+
+ def set_color(self, color):
+ self.color = color
+ self.refresh()
+
+ def refresh(self):
+ with g_lock:
+ self._win.attron(to_curses_attr(self.color))
+ self.addstr(0, 0, self.text)
+ self._win.attroff(to_curses_attr(self.color))
+ self._refresh()
+
+
class DummyInput(FieldInput, windows.Win):
"""
Used for fields that do not require any input ('fixed')
@@ -165,7 +187,7 @@ class BooleanWin(FieldInput, windows.Win):
def refresh(self):
with g_lock:
- self._win.attron(curses.color_pair(self.color))
+ self._win.attron(to_curses_attr(self.color))
self.addnstr(0, 0, ' '*(8), self.width)
self.addstr(0, 2, "%s"%self.value)
self.addstr(0, 8, '→')
@@ -174,7 +196,7 @@ class BooleanWin(FieldInput, windows.Win):
self.addstr(0, 8, '')
else:
self.addstr(0, 0, '')
- self._win.attroff(curses.color_pair(self.color))
+ self._win.attroff(to_curses_attr(self.color))
self._refresh()
def reply(self):
@@ -229,7 +251,7 @@ class TextMultiWin(FieldInput, windows.Win):
def refresh(self):
if not self.edition_input:
with g_lock:
- self._win.attron(curses.color_pair(self.color))
+ self._win.attron(to_curses_attr(self.color))
self.addnstr(0, 0, ' '*self.width, self.width)
option = self.options[self.val_pos]
self.addstr(0, self.width//2-len(option)//2, option)
@@ -237,7 +259,7 @@ class TextMultiWin(FieldInput, windows.Win):
self.addstr(0, 0, '←')
if self.val_pos < len(self.options)-1:
self.addstr(0, self.width-1, '→')
- self._win.attroff(curses.color_pair(self.color))
+ self._win.attroff(to_curses_attr(self.color))
self._refresh()
else:
self.edition_input.refresh()
@@ -281,7 +303,7 @@ class ListMultiWin(FieldInput, windows.Win):
def refresh(self):
with g_lock:
- self._win.attron(curses.color_pair(self.color))
+ self._win.attron(to_curses_attr(self.color))
self.addnstr(0, 0, ' '*self.width, self.width)
if self.val_pos > 0:
self.addstr(0, 0, '←')
@@ -290,7 +312,7 @@ class ListMultiWin(FieldInput, windows.Win):
option = self.options[self.val_pos]
self.addstr(0, self.width//2-len(option)//2, option[0]['label'])
self.addstr(0, 2, '✔' if option[1] else '☐')
- self._win.attroff(curses.color_pair(self.color))
+ self._win.attroff(to_curses_attr(self.color))
self._refresh()
def reply(self):
@@ -327,7 +349,7 @@ class ListSingleWin(FieldInput, windows.Win):
def refresh(self):
with g_lock:
- self._win.attron(curses.color_pair(self.color))
+ self._win.attron(to_curses_attr(self.color))
self.addnstr(0, 0, ' '*self.width, self.width)
if self.val_pos > 0:
self.addstr(0, 0, '←')
@@ -335,7 +357,7 @@ class ListSingleWin(FieldInput, windows.Win):
self.addstr(0, self.width-1, '→')
option = self.options[self.val_pos]['label']
self.addstr(0, self.width//2-len(option)//2, option)
- self._win.attroff(curses.color_pair(self.color))
+ self._win.attroff(to_curses_attr(self.color))
self._refresh()
def reply(self):
@@ -353,7 +375,7 @@ class TextSingleWin(FieldInput, windows.Input):
self.text = field.getValue() if isinstance(field.getValue(), str)\
else ""
self.pos = len(self.text)
- self.color = 14
+ self.color = (14, -1)
def reply(self):
self._field['label'] = ''
@@ -370,15 +392,15 @@ class TextPrivateWin(TextSingleWin):
with g_lock:
self._win.erase()
if self.color:
- self._win.attron(curses.color_pair(self.color))
+ self._win.attron(to_curses_attr(self.color))
self.addstr('*'*len(self.text[self.line_pos:self.line_pos+self.width-1]))
if self.color:
(y, x) = self._win.getyx()
size = self.width-x
- self.addnstr(' '*size, size, curses.color_pair(self.color))
+ self.addnstr(' '*size, size, to_curses_attr(self.color))
self.addstr(0, self.pos, '')
if self.color:
- self._win.attroff(curses.color_pair(self.color))
+ self._win.attroff(to_curses_attr(self.color))
self._refresh()
def get_help_message(self):
@@ -447,8 +469,8 @@ class FormWin(object):
return
if self.current_input == len(self.inputs) - 1 or self.current_input >= self.height-1:
return
- self.inputs[self.current_input]['label'].set_color(14)
- self.inputs[self.current_input]['input'].set_color(14)
+ self.inputs[self.current_input]['input'].set_color(get_theme().COLOR_NORMAL_TEXT)
+ self.inputs[self.current_input]['label'].set_color(get_theme().COLOR_NORMAL_TEXT)
self.current_input += 1
jump = 0
while self.current_input+jump != len(self.inputs) - 1 and self.inputs[self.current_input+jump]['input'].is_dummy():
@@ -456,16 +478,16 @@ class FormWin(object):
if self.inputs[self.current_input+jump]['input'].is_dummy():
return
self.current_input += jump
- self.inputs[self.current_input]['label'].set_color(13)
- self.inputs[self.current_input]['input'].set_color(13)
+ self.inputs[self.current_input]['input'].set_color(get_theme().COLOR_SELECTED_ROW)
+ self.inputs[self.current_input]['label'].set_color(get_theme().COLOR_SELECTED_ROW)
def go_to_previous_input(self):
if not self.inputs:
return
if self.current_input == 0:
return
- self.inputs[self.current_input]['label'].set_color(14)
- self.inputs[self.current_input]['input'].set_color(14)
+ self.inputs[self.current_input]['input'].set_color(get_theme().COLOR_NORMAL_TEXT)
+ self.inputs[self.current_input]['label'].set_color(get_theme().COLOR_NORMAL_TEXT)
self.current_input -= 1
jump = 0
while self.current_input-jump > 0 and self.inputs[self.current_input+jump]['input'].is_dummy():
@@ -473,8 +495,8 @@ class FormWin(object):
if self.inputs[self.current_input+jump]['input'].is_dummy():
return
self.current_input -= jump
- self.inputs[self.current_input]['label'].set_color(13)
- self.inputs[self.current_input]['input'].set_color(13)
+ self.inputs[self.current_input]['input'].set_color(get_theme().COLOR_SELECTED_ROW)
+ self.inputs[self.current_input]['label'].set_color(get_theme().COLOR_SELECTED_ROW)
def on_input(self, key):
if not self.inputs:
@@ -502,10 +524,11 @@ class FormWin(object):
break
inp['label'].refresh()
inp['input'].refresh()
+ inp['label'].refresh()
if self.current_input < self.height-1:
- self.inputs[self.current_input]['input'].set_color(13)
+ self.inputs[self.current_input]['input'].set_color(get_theme().COLOR_SELECTED_ROW)
self.inputs[self.current_input]['input'].refresh()
- self.inputs[self.current_input]['label'].set_color(13)
+ self.inputs[self.current_input]['label'].set_color(get_theme().COLOR_SELECTED_ROW)
self.inputs[self.current_input]['label'].refresh()
def refresh_current_input(self):
diff --git a/src/plugin_manager.py b/src/plugin_manager.py
index 1f0e89eb..df96e9ab 100644
--- a/src/plugin_manager.py
+++ b/src/plugin_manager.py
@@ -37,7 +37,7 @@ class PluginManager(object):
def load(self, name):
if name in self.plugins:
- self.plugins[name].unload()
+ self.unload(name)
try:
if name in self.modules:
diff --git a/src/tabs.py b/src/tabs.py
index 88d8ad7f..63fd2c96 100644
--- a/src/tabs.py
+++ b/src/tabs.py
@@ -681,6 +681,7 @@ 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))
@@ -799,7 +800,8 @@ class MucTab(ChatTab):
room.users.append(new_user)
if from_nick == room.own_nick:
room.joined = True
- self.send_chat_state('active')
+ 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
room.add_message(_("\x195}Your nickname is \x193}%s") % (from_nick))
if '170' in status_codes:
@@ -999,10 +1001,12 @@ 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):
@@ -1019,7 +1023,8 @@ class PrivateTab(ChatTab):
msg['body'] = xhtml.clean_text(line)
msg['xhtml_im'] = xhtml.poezio_colors_to_html(line)
if config.get('send_chat_states', 'true') == 'true' and self.remote_wants_chatstates is not False:
- msg['chat_state'] = 'active'
+ needed = 'inactive' if self.core.status.show in ('xa', 'away') else 'active'
+ msg['chat_state'] = needed
msg.send()
self.core.add_message_to_text_buffer(self.get_room(), line, None, self.core.own_nick or self.get_room().own_nick)
logger.log_message(JID(self.get_name()).bare, self.core.own_nick, line)
@@ -1033,9 +1038,35 @@ 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)
@@ -1124,22 +1155,25 @@ 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':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':get_theme().CHAR_QUIT, 'status': status_message.replace('"', '\\"')})
- self.deactivate()
- self.refresh()
- self.core.doupdate()
+ if self.core.current_tab() is self:
+ 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.refresh()
- self.core.doupdate()
+ self.get_room().add_message('\x194}%(spec)s \x193}%(nick)s\x195} joined the room' % {'nick':nick, 'spec':get_theme().CHAR_JOIN})
+ if self.core.current_tab() is self:
+ self.refresh()
+ self.core.doupdate()
+
def activate(self):
self.on = True
@@ -1185,6 +1219,7 @@ 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)
@@ -1527,7 +1562,8 @@ class ConversationTab(ChatTab):
msg['body'] = xhtml.clean_text(line)
msg['xhtml_im'] = xhtml.poezio_colors_to_html(line)
if config.get('send_chat_states', 'true') == 'true' and self.remote_wants_chatstates is not False:
- msg['chat_state'] = 'active'
+ needed = 'inactive' if self.core.status.show in ('xa', 'away') else 'active'
+ msg['chat_state'] = needed
msg.send()
self.core.add_message_to_text_buffer(self.get_room(), line, None, self.core.own_nick)
logger.log_message(JID(self.get_name()).bare, self.core.own_nick, line)
@@ -1541,6 +1577,7 @@ 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)
@@ -1658,6 +1695,7 @@ 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,
@@ -1792,6 +1830,7 @@ 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)