We can now chat with the same contact or join the same gc using two differenct account;

closes #1421
This commit is contained in:
Travis Shirk 2006-01-25 05:39:07 +00:00
parent 2b956ec93c
commit 170a1db254
5 changed files with 65 additions and 55 deletions

View File

@ -378,7 +378,7 @@ class ChatControlBase(MessageControl):
self.nb_unread += 1 self.nb_unread += 1
if gajim.interface.systray_enabled and self.notify_on_new_messages(): if gajim.interface.systray_enabled and self.notify_on_new_messages():
gajim.interface.systray.add_jid(jid, self.account, self.type_id) gajim.interface.systray.add_jid(jid, self.account, self.type_id)
self.parent_win.redraw_tab(self.contact) self.parent_win.redraw_tab(self)
if not self.parent_win.is_active(): if not self.parent_win.is_active():
self.parent_win.show_title(urgent) self.parent_win.show_title(urgent)
@ -492,7 +492,7 @@ class ChatControlBase(MessageControl):
#we are at the end #we are at the end
if self.nb_unread > 0: if self.nb_unread > 0:
self.nb_unread = 0 + self.get_specific_unread() self.nb_unread = 0 + self.get_specific_unread()
self.parent_win.redraw_tab(self.contact) self.parent_win.redraw_tab(self)
self.parent_win.show_title() self.parent_win.show_title()
if gajim.interface.systray_enabled: if gajim.interface.systray_enabled:
gajim.interface.systray.remove_jid(jid, gajim.interface.systray.remove_jid(jid,
@ -500,7 +500,7 @@ class ChatControlBase(MessageControl):
self.type_id) self.type_id)
self.msg_textview.grab_focus() self.msg_textview.grab_focus()
# Note, we send None chatstate to preserve current # Note, we send None chatstate to preserve current
self.parent_win.redraw_tab(self.contact) self.parent_win.redraw_tab(self)
def bring_scroll_to_end(self, textview, diff_y = 0): def bring_scroll_to_end(self, textview, diff_y = 0):
''' scrolls to the end of textview if end is not visible ''' ''' scrolls to the end of textview if end is not visible '''
@ -576,7 +576,7 @@ class ChatControlBase(MessageControl):
if self.conv_textview.at_the_end() and self.parent_win.window.is_active(): if self.conv_textview.at_the_end() and self.parent_win.window.is_active():
#we are at the end #we are at the end
self.nb_unread = self.get_specific_unread() self.nb_unread = self.get_specific_unread()
self.parent_win.redraw_tab(self.contact) self.parent_win.redraw_tab(self)
self.parent_win.show_title() self.parent_win.show_title()
if gajim.interface.systray_enabled: if gajim.interface.systray_enabled:
gajim.interface.systray.remove_jid(jid, self.account, gajim.interface.systray.remove_jid(jid, self.account,
@ -1197,7 +1197,7 @@ class ChatControl(ChatControlBase):
''' handle incoming chatstate that jid SENT TO us ''' ''' handle incoming chatstate that jid SENT TO us '''
self.draw_banner() self.draw_banner()
# update chatstate in tab for this chat # update chatstate in tab for this chat
self.parent_win.redraw_tab(self.contact, self.contact.chatstate) self.parent_win.redraw_tab(self, self.contact.chatstate)
def _on_banner_eventbox_button_press_event(self, widget, event): def _on_banner_eventbox_button_press_event(self, widget, event):
'''If right-clicked, show popup''' '''If right-clicked, show popup'''

View File

@ -443,8 +443,6 @@ class Interface:
# Handle chat states # Handle chat states
contact = gajim.contacts.get_first_contact_from_jid(account, jid) contact = gajim.contacts.get_first_contact_from_jid(account, jid)
if chat_control and chat_control.type_id == message_control.TYPE_CHAT: if chat_control and chat_control.type_id == message_control.TYPE_CHAT:
# FIXME: Why is this here?
#ctrl = gajim.interface.msg_win_mgr.get_control(jid,)
if chatstate is not None: # he or she sent us reply, so he supports jep85 if chatstate is not None: # he or she sent us reply, so he supports jep85
contact.chatstate = chatstate contact.chatstate = chatstate
if contact.our_chatstate == 'ask': # we were jep85 disco? if contact.our_chatstate == 'ask': # we were jep85 disco?

View File

@ -374,7 +374,7 @@ class GroupchatControl(ChatControlBase):
else: else:
kind = 'incoming' kind = 'incoming'
# muc-specific chatstate # muc-specific chatstate
self.parent_win.redraw_tab(self.contact, 'newmsg') self.parent_win.redraw_tab(self, 'newmsg')
else: else:
kind = 'status' kind = 'status'
@ -383,7 +383,7 @@ class GroupchatControl(ChatControlBase):
(highlight, sound) = self.highlighting_for_message(text, tim) (highlight, sound) = self.highlighting_for_message(text, tim)
if highlight: if highlight:
# muc-specific chatstate # muc-specific chatstate
self.parent_win.redraw_tab(self.contact, 'attention') self.parent_win.redraw_tab(self, 'attention')
other_tags_for_name.append('bold') other_tags_for_name.append('bold')
other_tags_for_text.append('marked') other_tags_for_text.append('marked')
if sound == 'received': if sound == 'received':
@ -662,7 +662,7 @@ class GroupchatControl(ChatControlBase):
c.status = status c.status = status
self.draw_contact(nick) self.draw_contact(nick)
self.parent_win.redraw_tab(self.contact) self.parent_win.redraw_tab(self)
if (time.time() - self.room_creation) > 30 and \ if (time.time() - self.room_creation) > 30 and \
nick != self.nick and statusCode != '303': nick != self.nick and statusCode != '303':
if show == 'offline': if show == 'offline':
@ -1047,7 +1047,7 @@ class GroupchatControl(ChatControlBase):
# add the focus-out line to the tab we are leaving # add the focus-out line to the tab we are leaving
self.check_and_possibly_add_focus_out_line() self.check_and_possibly_add_focus_out_line()
# Sending active to undo unread state # Sending active to undo unread state
self.parent_win.redraw_tab(self.contact, 'active') self.parent_win.redraw_tab(self, 'active')
def get_specific_unread(self): def get_specific_unread(self):
# returns the number of the number of unread msgs # returns the number of the number of unread msgs

View File

@ -42,6 +42,7 @@ class MessageWindow:
hid = 0 # drag_data_received handler id hid = 0 # drag_data_received handler id
def __init__(self, acct, type): def __init__(self, acct, type):
# A dictionary of dictionaries where _contacts[account][jid] == A MessageControl
self._controls = {} self._controls = {}
# If None, the window is not tied to any specific account # If None, the window is not tied to any specific account
self.account = acct self.account = acct
@ -93,6 +94,12 @@ class MessageWindow:
self.notebook.drag_dest_set(gtk.DEST_DEFAULT_ALL, self.DND_TARGETS, self.notebook.drag_dest_set(gtk.DEST_DEFAULT_ALL, self.DND_TARGETS,
gtk.gdk.ACTION_MOVE) gtk.gdk.ACTION_MOVE)
def get_num_controls(self):
n = 0
for dict in self._controls.values():
n += len(dict)
return n
def _on_window_focus(self, widget, event): def _on_window_focus(self, widget, event):
# window received focus, so if we had urgency REMOVE IT # window received focus, so if we had urgency REMOVE IT
# NOTE: we do not have to read the message (it maybe in a bg tab) # NOTE: we do not have to read the message (it maybe in a bg tab)
@ -104,11 +111,11 @@ class MessageWindow:
ctrl.set_control_active(True) ctrl.set_control_active(True)
# Undo "unread" state display, etc. # Undo "unread" state display, etc.
if ctrl.type_id == message_control.TYPE_GC: if ctrl.type_id == message_control.TYPE_GC:
self.redraw_tab(ctrl.contact, 'active') self.redraw_tab(ctrl, 'active')
else: else:
# NOTE: we do not send any chatstate to preserve # NOTE: we do not send any chatstate to preserve
# inactive, gone, etc. # inactive, gone, etc.
self.redraw_tab(ctrl.contact) self.redraw_tab(ctrl)
def _on_window_delete(self, win, event): def _on_window_delete(self, win, event):
# Make sure all controls are okay with being deleted # Make sure all controls are okay with being deleted
@ -123,8 +130,11 @@ class MessageWindow:
self._controls.clear() self._controls.clear()
def new_tab(self, control): def new_tab(self, control):
self._controls[control.contact.jid] = control if not self._controls.has_key(control.account):
if len(self._controls) > 1: self._controls[control.account] = {}
self._controls[control.account][control.contact.jid] = control
if self.get_num_controls() > 1:
self.notebook.set_show_tabs(True) self.notebook.set_show_tabs(True)
self.alignment.set_property('top-padding', 2) self.alignment.set_property('top-padding', 2)
@ -139,8 +149,7 @@ class MessageWindow:
self.setup_tab_dnd(control.widget) self.setup_tab_dnd(control.widget)
self.redraw_tab(control.contact) self.redraw_tab(control)
control.update_ui()
self.window.show_all() self.window.show_all()
# NOTE: we do not call set_control_active(True) since we don't know whether # NOTE: we do not call set_control_active(True) since we don't know whether
# the tab is the active one. # the tab is the active one.
@ -210,8 +219,7 @@ class MessageWindow:
gtkgui_helpers.set_unset_urgency_hint(self.window, False) gtkgui_helpers.set_unset_urgency_hint(self.window, False)
def set_active_tab(self, jid, acct): def set_active_tab(self, jid, acct):
# FIXME: Use acct ctrl = self._controls[acct][jid]
ctrl = self._controls[jid]
ctrl_page = self.notebook.page_num(ctrl.widget) ctrl_page = self.notebook.page_num(ctrl.widget)
self.notebook.set_current_page(ctrl_page) self.notebook.set_current_page(ctrl_page)
@ -230,15 +238,18 @@ class MessageWindow:
self.disconnect_tab_dnd(ctrl.widget) self.disconnect_tab_dnd(ctrl.widget)
self.notebook.remove_page(self.notebook.page_num(ctrl.widget)) self.notebook.remove_page(self.notebook.page_num(ctrl.widget))
del self._controls[ctrl.contact.jid] del self._controls[ctrl.account][ctrl.contact.jid]
if len(self._controls) == 1: # we are going from two tabs to one if len(self._controls[ctrl.account]) == 0:
del self._controls[ctrl.account]
if self.get_num_controls() == 1: # we are going from two tabs to one
show_tabs_if_one_tab = gajim.config.get('tabs_always_visible') show_tabs_if_one_tab = gajim.config.get('tabs_always_visible')
self.notebook.set_show_tabs(show_tabs_if_one_tab) self.notebook.set_show_tabs(show_tabs_if_one_tab)
if not show_tabs_if_one_tab: if not show_tabs_if_one_tab:
self.alignment.set_property('top-padding', 0) self.alignment.set_property('top-padding', 0)
self.show_title() self.show_title()
elif len(self._controls) == 0: elif self.get_num_controls() == 0:
# FIXME: These are not called when the window is destroyed like this, fake it # These are not called when the window is destroyed like this, fake it
gajim.interface.msg_win_mgr._on_window_delete(self.window, None) gajim.interface.msg_win_mgr._on_window_delete(self.window, None)
gajim.interface.msg_win_mgr._on_window_destroy(self.window) gajim.interface.msg_win_mgr._on_window_destroy(self.window)
# dnd clean up # dnd clean up
@ -247,8 +258,7 @@ class MessageWindow:
self.window.destroy() self.window.destroy()
def redraw_tab(self, contact, chatstate = None): def redraw_tab(self, ctrl, chatstate = None):
ctrl = self._controls[contact.jid]
ctrl.update_ui() ctrl.update_ui()
hbox = self.notebook.get_tab_label(ctrl.widget).get_children()[0] hbox = self.notebook.get_tab_label(ctrl.widget).get_children()[0]
@ -322,15 +332,14 @@ class MessageWindow:
def get_control(self, key, acct): def get_control(self, key, acct):
'''Return the MessageControl for jid or n, where n is a notebook page index. '''Return the MessageControl for jid or n, where n is a notebook page index.
When key is an int index acct may be None''' When key is an int index acct may be None'''
# FIXME: Use acct
if isinstance(key, str): if isinstance(key, str):
key = unicode(key, 'utf-8') key = unicode(key, 'utf-8')
if isinstance(key, unicode): if isinstance(key, unicode):
jid = key jid = key
for ctrl in self.controls(): try:
if ctrl.contact.jid == jid: return self._controls[acct][jid]
return ctrl except:
return None return None
else: else:
page_num = key page_num = key
@ -341,7 +350,8 @@ class MessageWindow:
return self._widget_to_control(nth_child) return self._widget_to_control(nth_child)
def controls(self): def controls(self):
for ctrl in self._controls.values(): for ctrl_dict in self._controls.values():
for ctrl in ctrl_dict.values():
yield ctrl yield ctrl
def update_print_time(self): def update_print_time(self):
@ -394,7 +404,7 @@ class MessageWindow:
def popup_menu(self, event): def popup_menu(self, event):
menu = self.get_active_control().prepare_context_menu() menu = self.get_active_control().prepare_context_menu()
# common menuitems (tab switches) # common menuitems (tab switches)
if len(self._controls) > 1: # if there is more than one tab if self.get_num_controls() > 1: # if there is more than one tab
menu.append(gtk.SeparatorMenuItem()) # seperator menu.append(gtk.SeparatorMenuItem()) # seperator
for ctrl in self.controls(): for ctrl in self.controls():
jid = ctrl.contact.jid jid = ctrl.contact.jid
@ -582,7 +592,7 @@ class MessageWindowMgr:
return None return None
def has_window(self, jid, acct): def has_window(self, jid, acct):
return self.get_window(jid, acct) return self.get_window(jid, acct) != None
def one_window_opened(self, contact, acct, type): def one_window_opened(self, contact, acct, type):
try: try:
@ -637,7 +647,7 @@ class MessageWindowMgr:
def _mode_to_key(self, contact, acct, type): def _mode_to_key(self, contact, acct, type):
if self.mode == self.CONFIG_NEVER: if self.mode == self.CONFIG_NEVER:
key = contact.jid key = acct + contact.jid
elif self.mode == self.CONFIG_ALWAYS: elif self.mode == self.CONFIG_ALWAYS:
key = self.MAIN_WIN key = self.MAIN_WIN
elif self.mode == self.CONFIG_PERACCT: elif self.mode == self.CONFIG_PERACCT:
@ -776,12 +786,14 @@ class MessageWindowMgr:
w.notebook.remove_page(0) w.notebook.remove_page(0)
page.unparent() page.unparent()
controls.append(ctrl) controls.append(ctrl)
# Must clear _controls from window to prevent MessageControl.shutdown calls
w._controls = {}
w.window.destroy() w.window.destroy()
self._windows = {} self._windows = {}
for ctrl in controls: for ctrl in controls:
mw = self.get_window(ctrl.contact.jid, ctr.account) mw = self.get_window(ctrl.contact.jid, ctrl.account)
if not mw: if not mw:
mw = self.create_window(ctrl.contact, ctrl.account, ctrl.type_id) mw = self.create_window(ctrl.contact, ctrl.account, ctrl.type_id)
ctrl.parent_win = mw ctrl.parent_win = mw

View File

@ -639,9 +639,9 @@ class RosterWindow:
for win in gajim.interface.msg_win_mgr.windows(): for win in gajim.interface.msg_win_mgr.windows():
win.repaint_themed_widgets() win.repaint_themed_widgets()
# update gc's roster # update gc's roster
for ctl in gajim.interface.msg_win_mgr.controls(): for ctrl in gajim.interface.msg_win_mgr.controls():
if ctl.type_id == message_control.TYPE_GC: if ctrl.type_id == message_control.TYPE_GC:
ctl.update_ui() ctrl.update_ui()
def draw_roster(self): def draw_roster(self):
'''Clear and draw roster''' '''Clear and draw roster'''
@ -729,19 +729,19 @@ class RosterWindow:
if gajim.interface.msg_win_mgr.has_window(contact.jid, account): if gajim.interface.msg_win_mgr.has_window(contact.jid, account):
jid = contact.jid jid = contact.jid
win = gajim.interface.msg_win_mgr.get_window(contact.jid, account) win = gajim.interface.msg_win_mgr.get_window(contact.jid, account)
ctl = win.get_control(jid, account) ctrl = win.get_control(jid, account)
ctl.update_ui() ctrl.update_ui()
win.redraw_tab(contact) win.redraw_tab(ctrl)
name = contact.get_shown_name() name = contact.get_shown_name()
if contact.resource != '': if contact.resource != '':
name += '/' + contact.resource name += '/' + contact.resource
uf_show = helpers.get_uf_show(show) uf_show = helpers.get_uf_show(show)
ctl.print_conversation(_('%s is now %s (%s)') % (name, uf_show, status), ctrl.print_conversation(_('%s is now %s (%s)') % (name, uf_show, status),
'status') 'status')
if contact == gajim.contacts.get_contact_with_highest_priority(account, if contact == gajim.contacts.get_contact_with_highest_priority(account,
contact.jid): contact.jid):
ctl.draw_banner() ctrl.draw_banner()
def on_info(self, widget, contact, account): def on_info(self, widget, contact, account):
'''Call vcard_information_window class to display contact's information''' '''Call vcard_information_window class to display contact's information'''
@ -924,8 +924,8 @@ class RosterWindow:
for u in gajim.contacts.get_contact(account, contact.jid): for u in gajim.contacts.get_contact(account, contact.jid):
u.keyID = keyID[0] u.keyID = keyID[0]
if gajim.interface.msg_win_mgr.has_window(contact.jid, account): if gajim.interface.msg_win_mgr.has_window(contact.jid, account):
ctl = gajim.interface.msg_win_mgr.get_control(contact.jid, account) ctrl = gajim.interface.msg_win_mgr.get_control(contact.jid, account)
ctl.update_ui() ctrl.update_ui()
keys_str = '' keys_str = ''
for jid in keys: for jid in keys:
keys_str += jid + ' ' + keys[jid] + ' ' keys_str += jid + ' ' + keys[jid] + ' '
@ -1789,8 +1789,8 @@ _('If "%s" accepts this request you will know his or her status.') % jid)
typ = '' typ = ''
if msg_type == 'error': if msg_type == 'error':
typ = 'status' typ = 'status'
ctl = gajim.interface.msg_win_mgr.get_control(jid, account) ctrl = gajim.interface.msg_win_mgr.get_control(jid, account)
ctl.print_conversation(msg, typ, tim = tim, encrypted = encrypted, ctrl.print_conversation(msg, typ, tim = tim, encrypted = encrypted,
subject = subject) subject = subject)
return return
@ -1982,14 +1982,14 @@ _('If "%s" accepts this request you will know his or her status.') % jid)
unread = True unread = True
for win in gajim.interface.msg_win_mgr.windows(): for win in gajim.interface.msg_win_mgr.windows():
unrd = 0 unrd = 0
for ctl in win.controls(): for ctrl in win.controls():
unrd += ctl.nb_unread unrd += ctrl.nb_unread
if unrd: if unrd:
unread = True unread = True
break break
for ctl in win.controls(): for ctrl in win.controls():
jid = ctl.contact.jid jid = ctrl.contact.jid
if gajim.last_message_time[acct].has_key(jid): if gajim.last_message_time[acct].has_key(jid):
if time.time() - gajim.last_message_time[acct][jid] < 2: if time.time() - gajim.last_message_time[acct][jid] < 2:
recent = True recent = True
@ -2253,9 +2253,9 @@ _('If "%s" accepts this request you will know his or her status.') % jid)
gajim.interface.systray.set_img() gajim.interface.systray.set_img()
for win in gajim.interface.msg_win_mgr.windows(): for win in gajim.interface.msg_win_mgr.windows():
for ctl in gajim.interface.msg_win_mgr.controls(): for ctrl in gajim.interface.msg_win_mgr.controls():
ctl.update_ui() ctrl.update_ui()
win.redraw_tab(ctl.contact) win.redraw_tab(ctrl)
self.update_status_combobox() self.update_status_combobox()