Welcome to mirror list, hosted at ThFree Co, Russian Federation.

dev.gajim.org/gajim/gajim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTravis Shirk <travis@pobox.com>2006-01-06 06:36:07 +0300
committerTravis Shirk <travis@pobox.com>2006-01-06 06:36:07 +0300
commit58f2d03dd35cf7dccc3885851d3c0292228d86b1 (patch)
treebfd99a90086212b2b8788736c7e07e7d87b65eaf
parentc4f4da5aef9afee290cb951d6572e84ea36274d4 (diff)
Groupchat roster work
-rw-r--r--src/chat_control.py19
-rw-r--r--src/common/contacts.py1
-rw-r--r--src/config.py10
-rwxr-xr-xsrc/gajim.py12
-rw-r--r--src/groupchat_control.py238
-rw-r--r--src/roster_window.py2
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'''