ConversationTab interface

parent 0f39961a
......@@ -162,3 +162,4 @@ comment =
roster_show_offline = false
own_nick = louiz’
\ No newline at end of file
......@@ -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):
......
......@@ -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()
......
......@@ -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):
......
......@@ -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)
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
......
......@@ -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:
txt = '%s' % contact.get_jid().bare
self.addstr(txt, curses.color_pair(theme.COLOR_INFORMATION_BAR))
resource = contact.get_highest_priority_resource()
else:
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):
"""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment