summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlouiz@4325f9fc-e183-4c21-96ce-0ab188b42d13 <louiz@4325f9fc-e183-4c21-96ce-0ab188b42d13>2010-11-10 21:15:08 +0000
committerlouiz@4325f9fc-e183-4c21-96ce-0ab188b42d13 <louiz@4325f9fc-e183-4c21-96ce-0ab188b42d13>2010-11-10 21:15:08 +0000
commit545902be7d625f29d00eceb1707afa36af20d137 (patch)
treec16da52b478c664560ec2e6b4008ca56d6a574f2
parent0f39961a5d12ecad0e8311c1f6eb6d54de3423ee (diff)
downloadpoezio-545902be7d625f29d00eceb1707afa36af20d137.tar.gz
poezio-545902be7d625f29d00eceb1707afa36af20d137.tar.bz2
poezio-545902be7d625f29d00eceb1707afa36af20d137.tar.xz
poezio-545902be7d625f29d00eceb1707afa36af20d137.zip
ConversationTab interface
-rw-r--r--data/default_config.cfg1
-rw-r--r--src/contact.py6
-rw-r--r--src/core.py25
-rw-r--r--src/roster.py11
-rw-r--r--src/tab.py52
-rw-r--r--src/window.py105
6 files changed, 146 insertions, 54 deletions
diff --git a/data/default_config.cfg b/data/default_config.cfg
index 12062dc8..5d1ddd5e 100644
--- a/data/default_config.cfg
+++ b/data/default_config.cfg
@@ -162,3 +162,4 @@ comment =
roster_show_offline = false
+own_nick = louiz’ \ No newline at end of file
diff --git a/src/contact.py b/src/contact.py
index 35a4a4a8..1eb41f72 100644
--- a/src/contact.py
+++ b/src/contact.py
@@ -14,12 +14,12 @@
# You should have received a copy of the GNU General Public License
# along with Poezio. If not, see <http://www.gnu.org/licenses/>.
-
"""
Defines the Resource and Contact classes
"""
-
from sleekxmpp.xmlstream.stanzabase import JID
+import logging
+log = logging.getLogger(__name__)
class Resource(object):
"""
@@ -54,7 +54,7 @@ class Resource(object):
def get_status(self):
return self._status
- def set__status(self, s):
+ def set_status(self, s):
self._status = s
class Contact(object):
diff --git a/src/core.py b/src/core.py
index 9dd72861..01770a49 100644
--- a/src/core.py
+++ b/src/core.py
@@ -94,7 +94,7 @@ class Core(object):
self.ignores = {}
self.resize_timer = None
self.previous_tab_nb = 0
-
+ self.own_nick = config.get('own_nick', self.xmpp.boundjid.bare)
self.commands = {
'help': (self.command_help, '\_o< KOIN KOIN KOIN'),
'join': (self.command_join, _("Usage: /join [room_name][@server][/nick] [password]\nJoin: Join the specified room. You can specify a nickname after a slash (/). If no nickname is specified, you will use the default_nick in the configuration file. You can omit the room name: you will then join the room you\'re looking at (useful if you were kicked). You can also provide a room_name without specifying a server, the server of the room you're currently in will be used. You can also provide a password to join the room.\nExamples:\n/join room@server.tld\n/join room@server.tld/John\n/join room2\n/join /me_again\n/join\n/join room@server.tld/my_nick password\n/join / password")),
@@ -199,7 +199,9 @@ class Core(object):
assert not resource
resource = Resource(jid.full)
status = presence['type']
+ status_message = presence['status']
priority = presence.getPriority() or 0
+ resource.set_status(status_message)
resource.set_presence(status)
resource.set_priority(priority)
contact.add_resource(resource)
@@ -216,7 +218,7 @@ class Core(object):
# request the roster
self.xmpp.getRoster()
# send initial presence
- self.xmpp.makePresence(pfrom=self.xmpp.boundjid.bare).send()
+ self.xmpp.makePresence().send()
rooms = config.get('rooms', '')
if rooms == '' or not isinstance(rooms, str):
return
@@ -478,16 +480,21 @@ class Core(object):
"""
"""
jid = presence['from']
+ log.debug('Presence Received: %s\n' % presence)
contact = roster.get_contact_by_jid(jid.bare)
+ log.debug('Contact: %s\n' % contact)
if not contact:
return
resource = contact.get_resource_by_fulljid(jid.full)
+ log.debug('Resource: %s\n' % resource)
if not resource:
return
status = presence['type']
+ status_message = presence['status']
priority = presence.getPriority() or 0
resource.set_presence(status)
resource.set_priority(priority)
+ resource.set_status(status_message)
if isinstance(self.current_tab(), RosterInfoTab):
self.refresh_window()
@@ -738,12 +745,12 @@ class Core(object):
self.add_message_to_text_buffer(room, _('You can join the room with an other nick, by typing "/join /other_nick"'))
self.refresh_window()
- def open_conversation_window(self, room_name, focus=True):
+ def open_conversation_window(self, jid, focus=True):
"""
open a new conversation tab and focus it if needed
"""
- r = Room(room_name, self.xmpp.boundjid.full)
- new_tab = ConversationTab(self.stdscr, self, r)
+ text_buffer = TextBuffer()
+ new_tab = ConversationTab(self.stdscr, self, text_buffer, jid)
# insert it in the rooms
if self.current_tab().nb == 0:
self.tabs.append(new_tab)
@@ -754,9 +761,8 @@ class Core(object):
break
if focus: # focus the room if needed
self.command_win('%s' % (new_tab.nb))
- # self.window.new_room(r)
self.refresh_window()
- return r
+ return text_buffer
def open_private_window(self, room_name, user_nick, focus=True):
complete_jid = room_name+'/'+user_nick
@@ -1393,11 +1399,12 @@ class Core(object):
def command_say(self, line):
if isinstance(self.current_tab(), PrivateTab):
muc.send_private_message(self.xmpp, self.current_tab().get_name(), line)
- elif isinstance(self.current_tab(), ConversationTab): # todo, special case
+ elif isinstance(self.current_tab(), ConversationTab): # todo, special case # hu, I can't remember what special case was needed when I wrote that…
muc.send_private_message(self.xmpp, self.current_tab().get_name(), line)
if isinstance(self.current_tab(), PrivateTab) or\
isinstance(self.current_tab(), ConversationTab):
- self.add_message_to_text_buffer(self.current_tab().get_room(), line, None, self.current_tab().get_room().own_nick)
+ log.debug('ALLO ICI\n\n')
+ self.add_message_to_text_buffer(self.current_tab().get_room(), line, None, self.own_nick)
elif isinstance(self.current_tab(), MucTab):
muc.send_groupchat_message(self.xmpp, self.current_tab().get_name(), line)
self.doupdate()
diff --git a/src/roster.py b/src/roster.py
index 09bc7b6b..610d73dc 100644
--- a/src/roster.py
+++ b/src/roster.py
@@ -18,9 +18,12 @@
"""
Defines the Roster and RosterGroup classes
"""
+import logging
+log = logging.getLogger(__name__)
from config import config
from contact import Contact, Resource
+from sleekxmpp.xmlstream.stanzabase import JID
class Roster(object):
def __init__(self):
@@ -47,8 +50,10 @@ class Roster(object):
"""
Returns the contact with the given bare JID
"""
- if jid in self._contacts:
- return self._contacts[jid]
+ # Use only the bare jid
+ jid = JID(jid)
+ if jid.bare in self._contacts:
+ return self._contacts[jid.bare]
return None
def edit_groups_of_contact(self, contact, groups):
@@ -59,7 +64,7 @@ class Roster(object):
# add the contact to each group he is in
# If the contact hasn't any group, we put her in
# the virtual default 'none' group
- if not len(groups):
+ if not len(groups):
groups = ['none']
for group in groups:
if group not in contact._groups:
diff --git a/src/tab.py b/src/tab.py
index 767ee353..3f3805cc 100644
--- a/src/tab.py
+++ b/src/tab.py
@@ -37,7 +37,6 @@ class Tab(object):
def __init__(self, stdscr, core):
self.core = core # a pointer to core, to access its attributes (ugly?)
- self.tab_type = "Tab"
self.nb = Tab.number
Tab.number += 1
self.size = (self.height, self.width) = stdscr.getmaxyx()
@@ -134,7 +133,6 @@ class InfoTab(Tab):
"""
def __init__(self, stdscr, core, name):
Tab.__init__(self, stdscr, core)
- self.tab_type = "InfoTab"
self.tab_win = window.GlobalInfoBar(1, self.width, self.height-2, 0, stdscr, self.visible)
self.text_win = window.TextWin(self.height-2, self.width, 0, 0, stdscr, self.visible)
self.input = window.Input(1, self.width, self.height-1, 0, stdscr, self.visible)
@@ -195,7 +193,6 @@ class MucTab(Tab):
terminal
"""
Tab.__init__(self, stdscr, core)
- self.tab_type = "MucTab"
self._room = room
self.topic_win = window.Topic(1, self.width, 0, 0, stdscr, self.visible)
self.text_win = window.TextWin(self.height-4-self.core.information_win_size, (self.width//10)*9, 1, 0, stdscr, self.visible)
@@ -313,7 +310,6 @@ class PrivateTab(Tab):
"""
def __init__(self, stdscr, core, room):
Tab.__init__(self, stdscr, core)
- self.tab_type = "PrivateTab"
self._room = room
self.text_win = window.TextWin(self.height-3-self.core.information_win_size, self.width, 0, 0, stdscr, self.visible)
self.info_header = window.PrivateInfoWin(1, self.width, self.height-3-self.core.information_win_size, 0, stdscr, self.visible)
@@ -358,10 +354,7 @@ class PrivateTab(Tab):
def on_gain_focus(self):
self._room.set_color_state(theme.COLOR_TAB_CURRENT)
- if not self.input.input_mode:
- curses.curs_set(1)
- else:
- curses.curs_set(0)
+ curses.curs_set(1)
def on_scroll_up(self):
self._room.scroll_up(self.text_win.height-1)
@@ -397,7 +390,6 @@ class RosterInfoTab(Tab):
"^F": self.start_search,
}
Tab.__init__(self, stdscr, core)
- self.tab_type = "RosterInfoTab"
self.name = "Roster"
roster_width = self.width//2
info_width = self.width-roster_width-1
@@ -534,11 +526,13 @@ class ConversationTab(Tab):
"""
The tab containg a normal conversation (someone from our roster)
"""
- def __init__(self, stdscr, core, room):
+ def __init__(self, stdscr, core, text_buffer, jid):
Tab.__init__(self, stdscr, core)
- self.tab_type = "ConversationTab"
- self._room = room
- self.text_win = window.TextWin(self.height-3-self.core.information_win_size, self.width, 0, 0, stdscr, self.visible)
+ self._text_buffer = text_buffer
+ self.color_state = theme.COLOR_TAB_NORMAL
+ self._name = jid # a conversation tab is linked to one specific full jid OR bare jid
+ self.text_win = window.TextWin(self.height-4-self.core.information_win_size, self.width, 1, 0, stdscr, self.visible)
+ self.upper_bar = window.ConversationStatusMessageWin(1, self.width, 0, 0, stdscr, self.visible)
self.info_header = window.ConversationInfoWin(1, self.width, self.height-3-self.core.information_win_size, 0, stdscr, self.visible)
self.info_win = window.TextWin(self.core.information_win_size, self.width, self.height-2-self.core.information_win_size, 0, stdscr, self.visible)
self.tab_win = window.GlobalInfoBar(1, self.width, self.height-2, 0, stdscr, self.visible)
@@ -547,47 +541,49 @@ class ConversationTab(Tab):
def resize(self, stdscr):
Tab.resize(self, stdscr)
self.text_win.resize(self.height-3-self.core.information_win_size, self.width, 0, 0, stdscr, self.visible)
+ self.upper_bar.resize(1, self.width, 0, 0, stdscr, self.visible)
self.info_header.resize(1, self.width, self.height-3-self.core.information_win_size, 0, stdscr, self.visible)
self.info_win.resize(self.core.information_win_size, self.width, self.height-2-self.core.information_win_size, 0, stdscr, self.visible)
self.tab_win.resize(1, self.width, self.height-2, 0, stdscr, self.visible)
self.input.resize(1, self.width, self.height-1, 0, stdscr, self.visible)
def refresh(self, tabs, informations, roster):
- self.text_win.refresh(self._room)
- # self.info_header.refresh(self._room, roster.get_contact_by_jid(self._room.name))
+ self.text_win.refresh(self._text_buffer)
+ self.upper_bar.refresh(self.get_name(), roster.get_contact_by_jid(self.get_name()))
+ self.info_header.refresh(self.get_name(), roster.get_contact_by_jid(self.get_name()), self._text_buffer)
self.info_win.refresh(informations)
self.tab_win.refresh(tabs, tabs[0])
self.input.refresh()
- curses.curs_set(1)
def get_color_state(self):
- if self._room.color_state == theme.COLOR_TAB_NORMAL or\
- self._room.color_state == theme.COLOR_TAB_CURRENT:
- return self._room.color_state
+ if self.color_state == theme.COLOR_TAB_NORMAL or\
+ self.color_state == theme.COLOR_TAB_CURRENT:
+ return self.color_state
return theme.COLOR_TAB_PRIVATE
def set_color_state(self, color):
- self._room.color_state = color
+ self.color_state = color
def get_name(self):
- return self._room.name
+ return self._name
def on_input(self, key):
return self.input.do_command(key)
def on_lose_focus(self):
- self._room.set_color_state(theme.COLOR_TAB_NORMAL)
- self._room.remove_line_separator()
- self._room.add_line_separator()
+ self.set_color_state(theme.COLOR_TAB_NORMAL)
+ self._text_buffer.remove_line_separator()
+ self._text_buffer.add_line_separator()
def on_gain_focus(self):
- self._room.set_color_state(theme.COLOR_TAB_CURRENT)
+ self.set_color_state(theme.COLOR_TAB_CURRENT)
+ curses.curs_set(1)
def on_scroll_up(self):
- self._room.scroll_up(self.text_win.height-1)
+ self._text_buffer.scroll_up(self.text_win.height-1)
def on_scroll_down(self):
- self._room.scroll_down(self.text_win.height-1)
+ self._text_buffer.scroll_down(self.text_win.height-1)
def on_info_win_size_changed(self, stdscr):
self.text_win.resize(self.height-3-self.core.information_win_size, self.width, 0, 0, stdscr, self.visible)
@@ -595,7 +591,7 @@ class ConversationTab(Tab):
self.info_win.resize(self.core.information_win_size, self.width, self.height-2-self.core.information_win_size, 0, stdscr, self.visible)
def get_room(self):
- return self._room
+ return self._text_buffer
def just_before_refresh(self):
return
diff --git a/src/window.py b/src/window.py
index 1c3f32d9..64113cfb 100644
--- a/src/window.py
+++ b/src/window.py
@@ -18,6 +18,9 @@ from gettext import (bindtextdomain, textdomain, bind_textdomain_codeset,
gettext as _)
from os.path import isfile
+import logging
+log = logging.getLogger(__name__)
+
import locale
locale.setlocale(locale.LC_ALL, '')
@@ -33,6 +36,8 @@ from roster import RosterGroup, roster
from message import Line
from tab import MIN_WIDTH, MIN_HEIGHT
+from sleekxmpp.xmlstream.stanzabase import JID
+
import theme
g_lock = Lock()
@@ -239,35 +244,113 @@ class PrivateInfoWin(InfoWin):
class ConversationInfoWin(InfoWin):
"""
The line above the information window, displaying informations
- about the MUC user we are talking to
+ about the user we are talking to
"""
+ color_show = {'xa':theme.COLOR_STATUS_XA,
+ 'none':theme.COLOR_STATUS_ONLINE,
+ '':theme.COLOR_STATUS_ONLINE,
+ 'available':theme.COLOR_STATUS_ONLINE,
+ 'dnd':theme.COLOR_STATUS_DND,
+ 'away':theme.COLOR_STATUS_AWAY,
+ 'chat':theme.COLOR_STATUS_CHAT,
+ 'unavailable':theme.COLOR_STATUS_UNAVAILABLE
+ }
+
def __init__(self, height, width, y, x, parent_win, visible):
InfoWin.__init__(self, height, width, y, x, parent_win, visible)
def resize(self, height, width, y, x, stdscr, visible):
self._resize(height, width, y, x, stdscr, visible)
- def refresh(self, room, contact):
+ def refresh(self, jid, contact, text_buffer):
if not self.visible:
return
# contact can be None, if we receive a message
# from someone not in our roster. In this case, we display
# only the maximum information from the message we can get.
- # Also, contact can be a resource, if we're talking to a
- # specific resource.
+ jid = JID(jid)
+ if contact:
+ if jid.resource:
+ resource = contact.get_resource_by_fulljid(jid.full)
+ else:
+ resource = contact.get_highest_priority_resource()
+ else:
+ resource = None
+ # if contact is None, then resource is None too: user is not in the roster
+ # so we don't know almost anything about it
+ # If contact is a Contact, then
+ # resource can now be a Resource: user is in the roster and online
+ # or resource is None: user is in the roster but offline
with g_lock:
self._win.erase()
- # self.write_room_name(resource, room)
- # self.print_scroll_position(room)
- # self.finish_line(theme.COLOR_INFORMATION_BAR)
+ self.write_contact_jid(jid)
+ self.write_contact_informations(contact)
+ self.write_resource_information(resource)
+ self.print_scroll_position(text_buffer)
+ self.finish_line(theme.COLOR_INFORMATION_BAR)
self._refresh()
- def write_room_name(self, contact, room):
+ def write_resource_information(self, resource):
+ """
+ Write the informations about the resource
+ """
+ if not resource:
+ presence = "unavailable"
+ else:
+ presence = resource.get_presence()
+ color = RosterWin.color_show[presence]
+ self.addstr('[', curses.color_pair(theme.COLOR_INFORMATION_BAR))
+ self.addstr(" ", curses.color_pair(color))
+ self.addstr(']', curses.color_pair(theme.COLOR_INFORMATION_BAR))
+
+ def write_contact_informations(self, contact):
+ """
+ Write the informations about the contact
+ """
if not contact:
- txt = '%s' % room.name
+ self.addstr("(contact not in roster)", curses.color_pair(theme.COLOR_INFORMATION_BAR))
+ return
+ display_name = contact.get_name() or contact.get_bare_jid()
+ self.addstr('%s '%(display_name), curses.color_pair(theme.COLOR_INFORMATION_BAR))
+
+ def write_contact_jid(self, jid):
+ """
+ Just write the jid that we are talking to
+ """
+ self.addstr('[', curses.color_pair(theme.COLOR_INFORMATION_BAR))
+ self.addstr(jid.full, curses.color_pair(10))
+ self.addstr('] ', curses.color_pair(theme.COLOR_INFORMATION_BAR))
+
+class ConversationStatusMessageWin(InfoWin):
+ """
+ The upper bar displaying the status message of the contact
+ """
+ def __init__(self, height, width, y, x, parent_win, visible):
+ InfoWin.__init__(self, height, width, y, x, parent_win, visible)
+
+ def resize(self, height, width, y, x, stdscr, visible):
+ self._resize(height, width, y, x, stdscr, visible)
+
+ def refresh(self, jid, contact):
+ if not self.visible:
+ return
+ jid = JID(jid)
+ if contact:
+ if jid.resource:
+ resource = contact.get_resource_by_fulljid(jid.full)
+ else:
+ resource = contact.get_highest_priority_resource()
else:
- txt = '%s' % contact.get_jid().bare
- self.addstr(txt, curses.color_pair(theme.COLOR_INFORMATION_BAR))
+ resource = None
+ with g_lock:
+ self._win.erase()
+ if resource:
+ self.write_status_message(resource)
+ self.finish_line(theme.COLOR_INFORMATION_BAR)
+ self._refresh()
+
+ def write_status_message(self, resource):
+ self.addstr(resource.get_status(), curses.color_pair(theme.COLOR_INFORMATION_BAR))
class MucInfoWin(InfoWin):
"""