diff options
author | Travis Shirk <travis@pobox.com> | 2006-01-06 06:36:07 +0300 |
---|---|---|
committer | Travis Shirk <travis@pobox.com> | 2006-01-06 06:36:07 +0300 |
commit | 58f2d03dd35cf7dccc3885851d3c0292228d86b1 (patch) | |
tree | bfd99a90086212b2b8788736c7e07e7d87b65eaf | |
parent | c4f4da5aef9afee290cb951d6572e84ea36274d4 (diff) |
Groupchat roster work
-rw-r--r-- | src/chat_control.py | 19 | ||||
-rw-r--r-- | src/common/contacts.py | 1 | ||||
-rw-r--r-- | src/config.py | 10 | ||||
-rwxr-xr-x | src/gajim.py | 12 | ||||
-rw-r--r-- | src/groupchat_control.py | 238 | ||||
-rw-r--r-- | src/roster_window.py | 2 |
6 files changed, 253 insertions, 29 deletions
diff --git a/src/chat_control.py b/src/chat_control.py index a231b0c95..bed6d8ce1 100644 --- a/src/chat_control.py +++ b/src/chat_control.py @@ -52,6 +52,9 @@ class ChatControlBase(MessageControl): Contains a banner, ConversationTextview, MessageTextView ''' + def draw_widgets(self): + self.draw_banner() + # Derived types MUST implement this def draw_banner(self): self._paint_banner() self._update_banner_state_image() @@ -59,9 +62,6 @@ class ChatControlBase(MessageControl): def update_state(self): self.draw_banner() # Derived types SHOULD implement this - def draw_widgets(self): - self.draw_banner() - # Derived types MUST implement this def repaint_themed_widgets(self): self.draw_banner() # NOTE: Derived classes MAY implement this @@ -650,6 +650,7 @@ class ChatControl(ChatControlBase): if self.contact.jid in gajim.encrypted_chats[self.account]: self.xml.get_widget('gpg_togglebutton').set_active(True) + self.draw_widgets() # restore previous conversation self.restore_conversation() @@ -1326,12 +1327,12 @@ class ChatControl(ChatControlBase): else: del gajim.awaiting_events[self.account][jid] typ = 'chat' # Is it a normal chat or a pm ? - # reset to status image in gc if it is a pm - # FIXME: New data structure - gcs = gajim.interface.instances[self.account]['gc'] - if gcs.has_key(room_jid): - gcs[room_jid].draw_all_roster() - typ = 'pm' +# # reset to status image in gc if it is a pm +# # FIXME: New data structure +# gcs = gajim.interface.instances[self.account]['gc'] +# if gcs.has_key(room_jid): +# gcs[room_jid].draw_all_roster() +# typ = 'pm' gajim.interface.roster.draw_contact(jid, self.account) if gajim.interface.systray_enabled: diff --git a/src/common/contacts.py b/src/common/contacts.py index ad257e617..73a45ecce 100644 --- a/src/common/contacts.py +++ b/src/common/contacts.py @@ -235,6 +235,7 @@ class Contacts: resource) def add_gc_contact(self, account, gc_contact): + print "add_gc_contact" # No such account before ? if not self._gc_contacts.has_key(account): self._contacts[account] = {gc_contact.room_jid : {gc_contact.name: \ diff --git a/src/config.py b/src/config.py index 9c7770898..756b8ff5e 100644 --- a/src/config.py +++ b/src/config.py @@ -480,13 +480,9 @@ class PreferencesWindow: def on_show_status_msgs_in_roster_checkbutton_toggled(self, widget): self.on_checkbutton_toggled(widget, 'show_status_msgs_in_roster') gajim.interface.roster.draw_roster() - for account in gajim.connections: - gcs = gajim.interface.instances[account]['gc'] - if gcs.has_key('tabbed'): - gcs['tabbed'].draw_all_roster() - else: - for room_jid in gcs: - gcs[room_jid].draw_all_roster() + for ctl in gajim.interface.msg_win_mgr.controls(): + if ctl.type_id == message_control.TYPE_GC: + ctl.draw_widgets() def on_show_avatars_in_roster_checkbutton_toggled(self, widget): self.on_checkbutton_toggled(widget, 'show_avatars_in_roster') diff --git a/src/gajim.py b/src/gajim.py index ddfbde14e..af10d4bfa 100755 --- a/src/gajim.py +++ b/src/gajim.py @@ -33,6 +33,8 @@ import sys import os import pygtk +import message_control + from common import exceptions from common import i18n i18n.init() @@ -404,7 +406,7 @@ class Interface: show_notification = True chat_control = gajim.interface.msg_win_mgr.get_control(jid) - if chat_control and chat_control.type_id == TYPE_GC: # it's a Private Message + if chat_control and chat_control.type_id == message_control.TYPE_GC: # it's a Private Message nick = gajim.get_nick_from_fjid(array[0]) fjid = array[0] if not gajim.interface.msg_win_mgr.has_window(fjid) and \ @@ -693,10 +695,10 @@ class Interface: 'status') ctl.draw_banner() - if self.instances[account]['gc'].has_key(room_jid): - self.instances[account]['gc'][room_jid].chg_contact_status(room_jid, - nick, show, status, array[4], array[5], array[6], array[7], - array[8], array[9], array[10], account) + gc_control = gajim.interface.msg_win_mgr.get_control(room_jid) + if gc_control: + gc_control.chg_contact_status(nick, show, status, array[4], array[5], array[6], + array[7], array[8], array[9], array[10]) if self.remote_ctrl: self.remote_ctrl.raise_signal('GCPresence', (account, array)) diff --git a/src/groupchat_control.py b/src/groupchat_control.py index b93a0bd3b..42c813e1b 100644 --- a/src/groupchat_control.py +++ b/src/groupchat_control.py @@ -12,6 +12,7 @@ ## GNU General Public License for more details. ## +import os import time import gtk import gtk.glade @@ -19,6 +20,16 @@ import pango import gobject import gtkgui_helpers import message_control +import tooltips +import dialogs +import vcard +import chat +import cell_renderer_image +import history_window +import tooltips + +from common import gajim +from common import helpers from common import gajim from chat_control import ChatControl @@ -64,6 +75,9 @@ class GroupchatControl(ChatControlBase): self.name = self.room_jid.split('@')[0] self.compact_view_always = gajim.config.get('always_compact_view_gc') + self.gc_refer_to_nick_char = gajim.config.get('gc_refer_to_nick_char') + + self._last_selected_contact = None # None or holds jid, account tuple # alphanum sorted self.muc_cmds = ['ban', 'chat', 'query', 'clear', 'close', 'compact', 'help', 'invite', 'join', 'kick', 'leave', 'me', 'msg', 'nick', 'part', 'say', 'topic'] @@ -78,6 +92,8 @@ class GroupchatControl(ChatControlBase): self.subject = '' self.subject_tooltip = gtk.Tooltips() + self.tooltip = tooltips.GCTooltip() + self.allow_focus_out_line = True # holds the iter's offset which points to the end of --- line self.focus_out_end_iter_offset = None @@ -88,14 +104,69 @@ class GroupchatControl(ChatControlBase): self.gc_popup_menu = xm.get_widget('gc_popup_menu') self.name_label = self.xml.get_widget('banner_name_label') - self.hpaneds = self.xml.get_widget('hpaned') + + # set the position of the current hpaned + self.hpaned_position = gajim.config.get('gc-hpaned-position') + self.hpaned = self.xml.get_widget('hpaned') + self.hpaned.set_position(self.hpaned_position) list_treeview = self.list_treeview = self.xml.get_widget('list_treeview') list_treeview.get_selection().connect('changed', self.on_list_treeview_selection_changed) list_treeview.connect('style-set', self.on_list_treeview_style_set) + # we want to know when the the widget resizes, because that is + # an indication that the hpaned has moved... + # FIXME: Find a better indicator that the hpaned has moved. + self.list_treeview.connect('size-allocate', self.on_treeview_size_allocate) + + #status_image, type, nickname, shown_nick + store = gtk.TreeStore(gtk.Image, str, str, str) + store.set_sort_column_id(C_TEXT, gtk.SORT_ASCENDING) + column = gtk.TreeViewColumn('contacts') + renderer_image = cell_renderer_image.CellRendererImage() + renderer_image.set_property('width', 20) + column.pack_start(renderer_image, expand = False) + column.add_attribute(renderer_image, 'image', 0) + renderer_text = gtk.CellRendererText() + column.pack_start(renderer_text, expand = True) + column.set_attributes(renderer_text, markup = C_TEXT) + column.set_cell_data_func(renderer_image, self.tree_cell_data_func, None) + column.set_cell_data_func(renderer_text, self.tree_cell_data_func, None) + + self.list_treeview.append_column(column) + self.list_treeview.set_model(store) + + # workaround to avoid gtk arrows to be shown + column = gtk.TreeViewColumn() # 2nd COLUMN + renderer = gtk.CellRendererPixbuf() + column.pack_start(renderer, expand = False) + self.list_treeview.append_column(column) + column.set_visible(False) + self.list_treeview.set_expander_column(column) + + # set an empty subject to show the room_jid + self.set_subject('') + self.got_disconnected() #init some variables + + self.draw_widgets() + self.conv_textview.grab_focus() + self.widget.show_all() + + def tree_cell_data_func(self, column, renderer, model, iter, data=None): + theme = gajim.config.get('roster_theme') + if model.iter_parent(iter): + bgcolor = gajim.config.get_per('themes', theme, 'contactbgcolor') + else: # it is root (eg. group) + bgcolor = gajim.config.get_per('themes', theme, 'groupbgcolor') + if bgcolor: + renderer.set_property('cell-background', bgcolor) + else: + renderer.set_property('cell-background', None) - self._last_selected_contact = None # None or holds jid, account tuple + def on_treeview_size_allocate(self, widget, allocation): + '''The MUC treeview has resized. Move the hpaned in all tabs to match''' + self.hpaned_position = self.hpaned.get_position() + self.hpaned.set_position(self.hpaned_position) def iter_contact_rows(self): '''iterate over all contact rows in the tree model''' @@ -117,7 +188,7 @@ class GroupchatControl(ChatControlBase): def on_list_treeview_selection_changed(self, selection): model, selected_iter = selection.get_selected() - self.draw_contact(nick) + self.draw_contact(self.nick) if self._last_selected_contact is not None: self.draw_contact(self._last_selected_contact) if selected_iter is None: @@ -205,7 +276,7 @@ class GroupchatControl(ChatControlBase): no_queue = False # We print if window is opened - pm_control = gajim.interface.get_control(fjid) + pm_control = gajim.interface.msg_win_mgr.get_control(fjid) if pm_control: pm_control.print_conversation(msg, tim = tim) return @@ -415,7 +486,7 @@ class GroupchatControl(ChatControlBase): subject = gtkgui_helpers.escape_for_pango_markup(subject) self.name_label.set_markup( '<span weight="heavy" size="x-large">%s</span>\n%s' % (self.room_jid, subject)) - event_box = name_label.get_parent() + event_box = self.name_label.get_parent() if subject == '': subject = _('This room has no subject') @@ -440,7 +511,6 @@ class GroupchatControl(ChatControlBase): def got_connected(self): gajim.gc_connected[self.account][self.room_jid] = True - message_textview = self.message_textviews[room_jid] self.msg_textview.set_sensitive(True) self.xml.get_widget('send_button').set_sensitive(True) @@ -456,8 +526,22 @@ class GroupchatControl(ChatControlBase): self.msg_textview.set_sensitive(False) self.xml.get_widget('send_button').set_sensitive(False) + def draw_widgets(self): + ChatControlBase.draw_widgets(self) + self.draw_roster() + + def draw_roster(self): + model = self.list_treeview.get_model() + model.clear() + print "draw_roster" + for nick in gajim.contacts.get_nick_list(self.account, self.room_jid): + gc_contact = gajim.contacts.get_gc_contact(self.account, self.room_jid, nick) + self.add_contact_to_roster(self.room_jid, nick, gc_contact.show, + gc_contact.role, gc_contact.affiliation, gc_contact.status, + gc_contact.jid) + def draw_contact(self, nick, selected=False, focus=False): - iter = self.get_contact_iter(self.room_jid, nick) + iter = self.get_contact_iter(nick) if not iter: return model = self.list_treeview.get_model() @@ -484,3 +568,143 @@ class GroupchatControl(ChatControlBase): model[iter][C_IMG] = image model[iter][C_TEXT] = name + + def chg_contact_status(self, nick, show, status, role, affiliation, jid, reason, actor, + statusCode, new_nick): + '''When an occupant changes his or her status''' + if show == 'invisible': + return + if not role: + role = 'visitor' + if not affiliation: + affiliation = 'none' + if show in ('offline', 'error'): + if statusCode == '307': + if actor is None: # do not print 'kicked by None' + s = _('%(nick)s has been kicked: %(reason)s') % { + 'nick': nick, + 'reason': reason } + else: + s = _('%(nick)s has been kicked by %(who)s: %(reason)s') % { + 'nick': nick, + 'who': actor, + 'reason': reason } + self.print_conversation(s) + elif statusCode == '301': + if actor is None: # do not print 'banned by None' + s = _('%(nick)s has been banned: %(reason)s') % { + 'nick': nick, + 'reason': reason } + else: + s = _('%(nick)s has been banned by %(who)s: %(reason)s') % { + 'nick': nick, + 'who': actor, + 'reason': reason } + self.print_conversation(s, self.room_jid) + elif statusCode == '303': # Someone changed his or her nick + if nick == self.nick: # We changed our nick + self.nick = new_nick + s = _('You are now known as %s') % new_nick + else: + s = _('%s is now known as %s') % (nick, new_nick) + self.print_conversation(s) + + if not gajim.awaiting_events[self.account].has_key(self.room_jid + '/' + nick): + self.remove_contact(nick) + else: + c = gajim.contacts.get_gc_contact(self.account, self.room_jid, nick) + c.show = show + c.status = status + if nick == self.nick and statusCode != '303': # We became offline + self.got_disconnected() + else: + iter = self.get_contact_iter(nick) + if not iter: + iter = self.add_contact_to_roster(nick, show, role, + affiliation, status, jid) + else: + actual_role = self.get_role(nick) + if role != actual_role: + self.remove_contact(nick) + self.add_contact_to_roster(nick, show, role, + affiliation, status, jid) + else: + c = gajim.contacts.get_gc_contact(self.account, self.room_jid, nick) + if c.show == show and c.status == status and \ + c.affiliation == affiliation: #no change + return + c.show = show + c.affiliation = affiliation + c.status = status + self.draw_contact(nick) + if (time.time() - self.room_creation) > 30 and \ + nick != self.nick and statusCode != '303': + if show == 'offline': + st = _('%s has left') % nick + else: + st = _('%s is now %s') % (nick, helpers.get_uf_show(show)) + if status: + st += ' (' + status + ')' + self.print_conversation(st) + + def add_contact_to_roster(self, nick, show, role, affiliation, status, jid = ''): + model = self.list_treeview.get_model() + role_name = helpers.get_uf_role(role, plural = True) + + resource = '' + if jid: + jids = jid.split('/', 1) + j = jids[0] + if len(jids) > 1: + resource = jids[1] + else: + j = '' + + name = nick + + role_iter = self.get_role_iter(role) + if not role_iter: + role_iter = model.append(None, + (gajim.interface.roster.jabber_state_images['16']['closed'], 'role', role, + '<b>%s</b>' % role_name)) + iter = model.append(role_iter, (None, 'contact', nick, name)) + if not nick in gajim.contacts.get_nick_list(self.account, self.room_jid): + gc_contact = gajim.contacts.create_gc_contact(room_jid = self.room_jid, + name = nick, show = show, status = status, role = role, + affiliation = affiliation, jid = j, resource = resource) + gajim.contacts.add_gc_contact(self.account, gc_contact) + self.draw_contact(nick) + if nick == self.nick: # we became online + self.got_connected() + self.list_treeview.expand_row((model.get_path(role_iter)), False) + return iter + + def get_role_iter(self, role): + model = self.list_treeview.get_model() + fin = False + iter = model.get_iter_root() + if not iter: + return None + while not fin: + role_name = model[iter][C_NICK].decode('utf-8') + if role == role_name: + return iter + iter = model.iter_next(iter) + if not iter: + fin = True + return None + + def remove_contact(self, nick): + '''Remove a user from the contacts_list''' + model = self.list_treeview.get_model() + iter = self.get_contact_iter(nick) + if not iter: + return + gc_contact = gajim.contacts.get_gc_contact(self.account, self.room_jid, nick) + if gc_contact: + gajim.contacts.remove_gc_contact(self.account, gc_contact) + parent_iter = model.iter_parent(iter) + model.remove(iter) + if model.iter_n_children(parent_iter) == 0: + model.remove(parent_iter) + diff --git a/src/roster_window.py b/src/roster_window.py index 7c438c3d5..318a6bebc 100644 --- a/src/roster_window.py +++ b/src/roster_window.py @@ -635,7 +635,7 @@ class RosterWindow: # update gc's roster for ctl in gajim.interface.msg_win_mgr.controls(): if ctl.type_id == message_control.TYPE_GC: - ctl.draw_all_roster() + ctl.draw_widgets() def draw_roster(self): '''Clear and draw roster''' |