summaryrefslogtreecommitdiff
path: root/src/tabs.py
diff options
context:
space:
mode:
authorFlorent Le Coz <louiz@louiz.org>2013-01-26 05:22:12 +0100
committerFlorent Le Coz <louiz@louiz.org>2013-01-26 05:35:07 +0100
commitdd2a6d1d6552476db671ad77d55d549122947954 (patch)
treef77d56b9dc6b72733f18db4655bd62cb737b7c54 /src/tabs.py
parent61f469bc128203a39a894f770bca67c18ad11a3e (diff)
downloadpoezio-dd2a6d1d6552476db671ad77d55d549122947954.tar.gz
poezio-dd2a6d1d6552476db671ad77d55d549122947954.tar.bz2
poezio-dd2a6d1d6552476db671ad77d55d549122947954.tar.xz
poezio-dd2a6d1d6552476db671ad77d55d549122947954.zip
Implement XEP 296 for locking resource in conversations.
With a few specific behaviours: When manually opening a conversation with a bare jid, we open a normal conversation that follows the XEP (locked and unlocked accordingly). If the user manually opens a conversation with a fulljid (by selecting a specific resource in the roster, or by specifying a fulljid to the /message command), we open a special tab that doesn’t follow the XEP (it is always locked to the same resource, and cannot be unlocked). When a message is received, unless a special tab has been manually opened by the other with that specific resource, we always send the messages to a uniq normal tab, unlocking or locking it according to the XEP. This means that only one tab can be opened with a given contact, unless the user specifically chooses to open a special tab for a specific resource. fixes #2159
Diffstat (limited to 'src/tabs.py')
-rw-r--r--src/tabs.py113
1 files changed, 96 insertions, 17 deletions
diff --git a/src/tabs.py b/src/tabs.py
index 2e39988d..fb47591b 100644
--- a/src/tabs.py
+++ b/src/tabs.py
@@ -525,7 +525,7 @@ class ChatTab(Tab):
self.core.information('Could not send custom xhtml', 'Error')
return
- msg = self.core.xmpp.make_message(self.get_name())
+ msg = self.core.xmpp.make_message(self.get_dest_jid())
msg['body'] = body
msg.enable('html')
msg['html']['body'] = arg
@@ -536,6 +536,9 @@ class ChatTab(Tab):
self.refresh()
msg.send()
+ def get_dest_jid(self):
+ return self.get_name()
+
@refresh_wrapper.always
def command_clear(self, args):
"""
@@ -551,7 +554,7 @@ class ChatTab(Tab):
if not isinstance(self, MucTab) or self.joined:
if state in ('active', 'inactive', 'gone') and self.inactive and not always_send:
return
- msg = self.core.xmpp.make_message(self.get_name())
+ msg = self.core.xmpp.make_message(self.get_dest_jid())
msg['type'] = self.message_type
msg['chat_state'] = state
self.chat_state = state
@@ -2883,6 +2886,7 @@ class RosterInfoTab(Tab):
class ConversationTab(ChatTab):
"""
The tab containg a normal conversation (not from a MUC)
+ Must not be instantiated, use Static or Dynamic version only.
"""
plugin_commands = {}
plugin_keys = {}
@@ -2895,7 +2899,6 @@ class ConversationTab(ChatTab):
self.text_win = windows.TextWin()
self._text_buffer.add_window(self.text_win)
self.upper_bar = windows.ConversationStatusMessageWin()
- self.info_header = windows.ConversationInfoWin()
self.input = windows.MessageInput()
self.check_attention()
# keys
@@ -2938,7 +2941,7 @@ class ConversationTab(ChatTab):
self.complete_commands(self.input)
def command_say(self, line, attention=False, correct=False):
- msg = self.core.xmpp.make_message(self.get_name())
+ msg = self.core.xmpp.make_message(self.get_dest_jid())
msg['type'] = 'chat'
msg['body'] = line
# trigger the event BEFORE looking for colors.
@@ -2966,7 +2969,7 @@ class ConversationTab(ChatTab):
self.core.events.trigger('conversation_say_after', msg, self)
self.last_sent_message = msg
msg.send()
- logger.log_message(safeJID(self.get_name()).bare, self.core.own_nick, line)
+ logger.log_message(safeJID(self.get_dest_jid()).bare, self.core.own_nick, line)
self.cancel_paused_delay()
self.text_win.refresh()
self.input.refresh()
@@ -3007,8 +3010,8 @@ class ConversationTab(ChatTab):
@refresh_wrapper.conditional
def command_info(self, arg):
- contact = roster[self.get_name()]
- jid = safeJID(self.get_name())
+ contact = roster[self.get_dest_jid()]
+ jid = safeJID(self.get_dest_jid())
if jid.resource:
resource = contact[jid.full]
else:
@@ -3021,13 +3024,13 @@ class ConversationTab(ChatTab):
if message is not '':
self.command_say(message, attention=True)
else:
- msg = self.core.xmpp.make_message(self.get_name())
+ msg = self.core.xmpp.make_message(self.get_dest_jid())
msg['type'] = 'chat'
msg['attention'] = True
msg.send()
def check_attention(self):
- self.core.xmpp.plugin['xep_0030'].get_info(jid=self.get_name(), block=False, timeout=5, callback=self.on_attention_checked)
+ self.core.xmpp.plugin['xep_0030'].get_info(jid=self.get_dest_jid(), block=False, timeout=5, callback=self.on_attention_checked)
def on_attention_checked(self, iq):
if 'urn:xmpp:attention:0' in iq['disco_info'].get_features():
@@ -3076,14 +3079,14 @@ class ConversationTab(ChatTab):
self.resize()
log.debug(' TAB Refresh: %s',self.__class__.__name__)
self.text_win.refresh()
- self.upper_bar.refresh(self.get_name(), roster[self.get_name()])
- self.info_header.refresh(self.get_name(), roster[self.get_name()], self.text_win, self.chatstate, ConversationTab.additional_informations)
+ self.upper_bar.refresh(self.get_dest_jid(), roster[self.get_dest_jid()])
+ self.info_header.refresh(self.get_dest_jid(), roster[self.get_dest_jid()], self.text_win, self.chatstate, ConversationTab.additional_informations)
self.info_win.refresh()
self.refresh_tab_win()
self.input.refresh()
def refresh_info_header(self):
- self.info_header.refresh(self.get_name(), roster[self.get_name()],
+ self.info_header.refresh(self.get_dest_jid(), roster[self.get_dest_jid()],
self.text_win, self.chatstate, ConversationTab.additional_informations)
self.input.refresh()
@@ -3108,8 +3111,8 @@ class ConversationTab(ChatTab):
return False
def on_lose_focus(self):
- contact = roster[self.get_name()]
- jid = safeJID(self.get_name())
+ contact = roster[self.get_dest_jid()]
+ jid = safeJID(self.get_dest_jid())
if contact:
if jid.resource:
resource = contact[jid.full]
@@ -3125,8 +3128,8 @@ class ConversationTab(ChatTab):
self.send_chat_state('inactive')
def on_gain_focus(self):
- contact = roster[self.get_name()]
- jid = safeJID(self.get_name())
+ contact = roster[self.get_dest_jid()]
+ jid = safeJID(self.get_dest_jid())
if contact:
if jid.resource:
resource = contact[jid.full]
@@ -3178,6 +3181,83 @@ class ConversationTab(ChatTab):
res.append(contact.name)
return res
+class DynamicConversationTab(ConversationTab):
+ """
+ A conversation tab associated with one bare JID that can be “locked” to
+ a full jid, and unlocked, as described in the XEP-0296.
+ Only one DynamicConversationTab can be opened for a given jid.
+ """
+ def __init__(self, jid, resource=None):
+ self.locked_resource = None
+ self.name = safeJID(jid).bare
+ if resource:
+ self.lock(resource)
+ self.info_header = windows.DynamicConversationInfoWin()
+ ConversationTab.__init__(self, jid)
+
+ def lock(self, resource):
+ """
+ Lock the tab to the resource.
+ """
+ assert(resource)
+ self.locked_resource = resource
+
+ def unlock(self):
+ """
+ Unlock the tab from a resource. It is now “associated” with the bare
+ jid.
+ """
+ self.locked_resource = None
+
+ def get_dest_jid(self):
+ """
+ Returns the full jid (using the locked resource), or the bare jid if
+ the conversation is not locked.
+ """
+ if self.locked_resource:
+ return "%s/%s" % (self.get_name(), self.locked_resource)
+ return self.get_name()
+
+ def refresh(self):
+ """
+ Different from the parent class only for the info_header object.
+ """
+ if self.need_resize:
+ self.resize()
+ log.debug(' TAB Refresh: %s',self.__class__.__name__)
+ self.text_win.refresh()
+ self.upper_bar.refresh(self.get_name(), roster[self.get_name()])
+ if self.locked_resource:
+ displayed_jid = "%s/%s" % (self.get_name(), self.locked_resource)
+ else:
+ displayed_jid = self.get_name()
+ self.info_header.refresh(displayed_jid, roster[self.get_name()], self.text_win, self.chatstate, ConversationTab.additional_informations)
+ self.info_win.refresh()
+ self.refresh_tab_win()
+ self.input.refresh()
+
+ def refresh_info_header(self):
+ """
+ Different from the parent class only for the info_header object.
+ """
+ if self.locked_resource:
+ displayed_jid = "%s/%s" % (self.get_name(), self.locked_resource)
+ else:
+ displayed_jid = self.get_name()
+ self.info_header.refresh(displayed_jid, roster[self.get_name()],
+ self.text_win, self.chatstate, ConversationTab.additional_informations)
+ self.input.refresh()
+
+class StaticConversationTab(ConversationTab):
+ """
+ A conversation tab associated with one Full JID. It cannot be locked to
+ an different resource or unlocked.
+ """
+ def __init__(self, jid):
+ assert(safeJID(jid).resource)
+ self.info_header = windows.ConversationInfoWin()
+ ConversationTab.__init__(self, jid)
+
class MucListTab(Tab):
"""
A tab listing rooms from a specific server, displaying various information,
@@ -3528,7 +3608,6 @@ class XMLTab(Tab):
self.text_win.resize(self.height-2-self.core.information_win_size - Tab.tab_win_height(), self.width, 0, 0)
self.info_header.resize(1, self.width, self.height-2-self.core.information_win_size - Tab.tab_win_height(), 0)
-
class SimpleTextTab(Tab):
"""
A very simple tab, with just a text displaying some