spread presence handler into classes that really need it

This commit is contained in:
Yann Leboulanger 2010-09-23 20:46:47 +02:00
parent 180178608d
commit 2476506338
5 changed files with 239 additions and 225 deletions

View File

@ -1115,6 +1115,8 @@ ConnectionJingle, ConnectionIBBytestream):
self._nec_gmail_new_mail_received)
gajim.ged.register_event_handler('ping-received', ged.CORE,
self._nec_ping_received)
gajim.ged.register_event_handler('presence-received', ged.CORE,
self._nec_presence_received)
def build_http_auth_answer(self, iq_obj, answer):
if not self.connection or self.connected < 2:
@ -1743,6 +1745,131 @@ ConnectionJingle, ConnectionIBBytestream):
gajim.nec.push_incoming_event(NetworkEvent('raw-pres-received',
conn=self, iq_obj=prs))
def _nec_presence_received(self, obj):
account = obj.conn.name
jid = obj.jid
resource = obj.resource or ''
statuss = ['offline', 'error', 'online', 'chat', 'away', 'xa', 'dnd',
'invisible']
obj.old_show = 0
obj.new_show = statuss.index(obj.show)
obj.contact_list = []
highest = gajim.contacts.get_contact_with_highest_priority(account, jid)
obj.was_highest = (highest and highest.resource == resource)
# Update contact
obj.contact_list = gajim.contacts.get_contacts(account, jid)
obj.contact = None
resources = []
for c in obj.contact_list:
resources.append(c.resource)
if c.resource == resource:
obj.contact = c
break
if obj.contact:
obj.old_show = statuss.index(obj.contact.show)
# nick changed
if obj.contact_nickname is not None and \
obj.contact.contact_name != obj.contact_nickname:
obj.contact.contact_name = obj.contact_nickname
obj.need_redraw = True
# gajim.interface.roster.draw_contact(jid, account)
if obj.old_show == obj.new_show and obj.contact.status == \
obj.status and obj.contact.priority == obj.prio: # no change
return
else:
obj.contact = gajim.contacts.get_first_contact_from_jid(account,
jid)
if not obj.contact:
# Presence of another resource of our jid
# Create self contact and add to roster
if resource == obj.conn.server_resource:
return
# Ignore offline presence of unknown self resource
if obj.new_show < 2:
return
obj.contact = gajim.contacts.create_self_contact(jid=jid,
account=account, show=obj.show, status=obj.status,
priority=obj.prio, keyID=obj.keyID,
resource=obj.resource)
gajim.contacts.add_contact(account, obj.contact)
obj.contact_list.append(obj.contact)
else:
obj.old_show = statuss.index(obj.contact.show)
if (resources != [''] and (len(obj.contact_list) != 1 or \
obj.contact_list[0].show != 'offline')) and \
not gajim.jid_is_transport(jid):
# Another resource of an existing contact connected
obj.old_show = 0
obj.contact = gajim.contacts.copy_contact(obj.contact)
obj.contact_list.append(obj.contact)
obj.contact.resource = resource
obj.need_add_in_roster = True
# gajim.interface.roster.add_contact(jid, account)
if not gajim.jid_is_transport(jid) and len(obj.contact_list) == 1:
# It's not an agent
if obj.old_show == 0 and obj.new_show > 1:
if not jid in gajim.newly_added[account]:
gajim.newly_added[account].append(jid)
if jid in gajim.to_be_removed[account]:
gajim.to_be_removed[account].remove(jid)
elif obj.old_show > 1 and obj.new_show == 0 and \
obj.conn.connected > 1:
if not jid in gajim.to_be_removed[account]:
gajim.to_be_removed[account].append(jid)
if jid in gajim.newly_added[account]:
gajim.newly_added[account].remove(jid)
obj.need_redraw = True
# self.roster.draw_contact(jid, account)
obj.contact.show = obj.show
obj.contact.status = obj.status
obj.contact.priority = obj.prio
obj.contact.keyID = obj.keyID
if obj.timestamp:
obj.contact.last_status_time = obj.timestamp
elif not gajim.block_signed_in_notifications[account]:
# We're connected since more that 30 seconds
obj.contact.last_status_time = localtime()
obj.contact.contact_nickname = obj.contact_nickname
if gajim.jid_is_transport(jid):
return
# It isn't an agent
# reset chatstate if needed:
# (when contact signs out or has errors)
if obj.show in ('offline', 'error'):
obj.contact.our_chatstate = obj.contact.chatstate = \
obj.contact.composing_xep = None
# TODO: This causes problems when another
# resource signs off!
self.stop_all_active_file_transfers(obj.contact)
# disable encryption, since if any messages are
# lost they'll be not decryptable (note that
# this contradicts XEP-0201 - trying to get that
# in the XEP, though)
# there won't be any sessions here if the contact terminated
# their sessions before going offline (which we do)
for sess in self.get_sessions(jid):
if obj.fjid != str(sess.jid):
continue
if sess.control:
sess.control.no_autonegotiation = False
if sess.enable_encryption:
sess.terminate_e2e()
self.delete_session(jid, sess.thread_id)
def _StanzaArrivedCB(self, con, obj):
self.last_io = gajim.idlequeue.current_time()

View File

@ -604,6 +604,10 @@ class PresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
def generate(self):
self.conn = self.base_event.conn
self.iq_obj = self.base_event.iq_obj
self.need_add_in_roster = False
self.need_redraw = False
self.ptype = self.iq_obj.getType()
if self.ptype == 'available':
self.ptype = None
@ -627,6 +631,10 @@ class PresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
_('Nickname not allowed: %s') % resource, None, False, None,
[]))
return
jid_list = gajim.contacts.get_jid_list(self.conn.name)
# if self.jid not in jid_list and self.jid != gajim.get_jid_from_account(
# self.conn.name):
# return
self.timestamp = None
self.get_id()
self.is_gc = False # is it a GC presence ?
@ -957,5 +965,5 @@ class PresenceReceivedEvent(nec.NetworkIncomingEvent, HelperEvent):
self.conn.server_resource:
# We got our own presence
self.conn.dispatch('STATUS', self.show)
else:
elif self.jid in jid_list:
return True

View File

@ -995,12 +995,17 @@ _('Please fill in the data of the contact you want to add in account %s') % acco
message_buffer.set_text(helpers.get_subscription_request_msg(
self.account))
gajim.ged.register_event_handler('presence-received', ged.GUI1,
self._nec_presence_received)
def on_add_new_contact_window_destroy(self, widget):
if self.account:
location = gajim.interface.instances[self.account]
else:
location = gajim.interface.instances
del location['add_contact']
gajim.ged.remove_event_handler('presence-received', ged.GUI1,
self._nec_presence_received)
def on_register_button_clicked(self, widget):
jid = self.protocol_jid_combobox.get_active_text().decode('utf-8')
@ -1154,6 +1159,14 @@ _('Please fill in the data of the contact you want to add in account %s') % acco
self.connected_label.show()
self.add_button.set_sensitive(False)
def _nec_presence_received(self, obj):
if gajim.jid_is_transport(obj.jid):
if obj.old_show == 0 and obj.new_show > 1:
self.transport_signed_in(obj.jid)
elif obj.old_show > 1 and obj.new_show == 0:
self.transport_signed_out(obj.jid)
class AboutDialog:
"""
Class for about dialog

View File

@ -290,249 +290,76 @@ class Interface:
#
# Contact changed show
# FIXME: Drop and rewrite...
statuss = ['offline', 'error', 'online', 'chat', 'away', 'xa', 'dnd',
'invisible']
account = obj.conn.name
jid = obj.jid
show = obj.show
status = obj.status
resource = obj.resource or ''
priority = obj.prio
keyID = obj.keyID
timestamp = obj.timestamp
contact_nickname = obj.contact_nickname
obj.old_show = 0
obj.new_show = statuss.index(show)
lcontact = []
highest = gajim.contacts.get_contact_with_highest_priority(account, jid)
was_highest = (highest and highest.resource == resource)
# Update contact
jid_list = gajim.contacts.get_jid_list(account)
if jid in jid_list or jid == gajim.get_jid_from_account(account):
lcontact = gajim.contacts.get_contacts(account, jid)
contact1 = None
resources = []
for c in lcontact:
resources.append(c.resource)
if c.resource == resource:
contact1 = c
break
if contact1:
if contact1.show in statuss:
obj.old_show = statuss.index(contact1.show)
# nick changed
if contact_nickname is not None and \
contact1.contact_name != contact_nickname:
contact1.contact_name = contact_nickname
self.roster.draw_contact(jid, account)
if obj.old_show == obj.new_show and contact1.status == status \
and contact1.priority == priority: # no change
return
else:
contact1 = gajim.contacts.get_first_contact_from_jid(account,
jid)
if not contact1:
# Presence of another resource of our
# jid
# Create self contact and add to roster
if resource == obj.conn.server_resource:
return
# Ignore offline presence of unknown self resource
if obj.new_show < 2:
return
contact1 = gajim.contacts.create_self_contact(jid=jid,
account=account, show=show, status=status,
priority=priority, keyID=keyID, resource=resource)
obj.old_show = 0
gajim.contacts.add_contact(account, contact1)
lcontact.append(contact1)
elif contact1.show in statuss:
obj.old_show = statuss.index(contact1.show)
if (resources != [''] and (len(lcontact) != 1 or \
lcontact[0].show != 'offline')) and \
not gajim.jid_is_transport(jid):
# Another resource of an existing contact connected
obj.old_show = 0
contact1 = gajim.contacts.copy_contact(contact1)
lcontact.append(contact1)
contact1.resource = resource
self.roster.add_contact(contact1.jid, account)
if not gajim.jid_is_transport(contact1.jid) and len(lcontact) == 1:
# It's not an agent
if obj.old_show == 0 and obj.new_show > 1:
if not contact1.jid in gajim.newly_added[account]:
gajim.newly_added[account].append(contact1.jid)
if contact1.jid in gajim.to_be_removed[account]:
gajim.to_be_removed[account].remove(contact1.jid)
gobject.timeout_add_seconds(5,
self.roster.remove_newly_added, contact1.jid, account)
elif obj.old_show > 1 and obj.new_show == 0 and \
obj.conn.connected > 1:
if not contact1.jid in gajim.to_be_removed[account]:
gajim.to_be_removed[account].append(contact1.jid)
if contact1.jid in gajim.newly_added[account]:
gajim.newly_added[account].remove(contact1.jid)
self.roster.draw_contact(contact1.jid, account)
gobject.timeout_add_seconds(5,
self.roster.remove_to_be_removed, contact1.jid, account)
# unset custom status
if (obj.old_show == 0 and obj.new_show > 1) or \
(obj.old_show > 1 and obj.new_show == 0 and obj.conn.connected > 1):
if account in self.status_sent_to_users and \
jid in self.status_sent_to_users[account]:
del self.status_sent_to_users[account][jid]
contact1.show = show
contact1.status = status
contact1.priority = priority
contact1.keyID = keyID
if timestamp:
contact1.last_status_time = timestamp
elif not gajim.block_signed_in_notifications[account]:
# We're connected since more that 30 seconds
contact1.last_status_time = time.localtime()
contact1.contact_nickname = contact_nickname
# unset custom status
if (obj.old_show == 0 and obj.new_show > 1) or \
(obj.old_show > 1 and obj.new_show == 0 and obj.conn.connected > 1):
if account in self.status_sent_to_users and \
jid in self.status_sent_to_users[account]:
del self.status_sent_to_users[account][jid]
if gajim.jid_is_transport(jid):
# It must be an agent
if jid in jid_list:
# Update existing iter and group counting
self.roster.draw_contact(jid, account)
self.roster.draw_group(_('Transports'), account)
if obj.new_show > 1 and jid in gajim.transport_avatar[account]:
# transport just signed in.
# request avatars
for jid_ in gajim.transport_avatar[account][jid]:
obj.conn.request_vcard(jid_)
# transport just signed in/out, don't show
# popup notifications for 30s
account_jid = account + '/' + jid
gajim.block_signed_in_notifications[account_jid] = True
gobject.timeout_add_seconds(30,
self.unblock_signed_in_notifications, account_jid)
locations = (self.instances, self.instances[account])
for location in locations:
if 'add_contact' in location:
if obj.old_show == 0 and obj.new_show > 1:
location['add_contact'].transport_signed_in(jid)
break
elif obj.old_show > 1 and obj.new_show == 0:
location['add_contact'].transport_signed_out(jid)
break
elif jid in jid_list:
# It isn't an agent
# reset chatstate if needed:
# (when contact signs out or has errors)
if show in ('offline', 'error'):
contact1.our_chatstate = contact1.chatstate = \
contact1.composing_xep = None
# TODO: This causes problems when another
# resource signs off!
obj.conn.stop_all_active_file_transfers(contact1)
# transport just signed in/out, don't show
# popup notifications for 30s
account_jid = account + '/' + jid
gajim.block_signed_in_notifications[account_jid] = True
gobject.timeout_add_seconds(30,
self.unblock_signed_in_notifications, account_jid)
# disable encryption, since if any messages are
# lost they'll be not decryptable (note that
# this contradicts XEP-0201 - trying to get that
# in the XEP, though)
# there won't be any sessions here if the contact terminated
# their sessions before going offline (which we do)
for sess in obj.conn.get_sessions(jid):
if obj.fjid != str(sess.jid):
continue
if sess.control:
sess.control.no_autonegotiation = False
if sess.enable_encryption:
sess.terminate_e2e()
obj.conn.delete_session(jid, sess.thread_id)
self.roster.chg_contact_status(contact1, show, status, account)
# Notifications
if obj.old_show < 2 and obj.new_show > 1:
show_notif = True
for c in lcontact:
if c.resource == resource:
# we look for other connected resources
continue
if c.show not in ('offline', 'error'):
show_notif = False
break
if show_notif:
# no other resource is connected, let's look in metacontacts
family = gajim.contacts.get_metacontacts_family(account,
jid)
for info in family:
acct_ = info['account']
jid_ = info['jid']
c_ = gajim.contacts.get_contact_with_highest_priority(
acct_, jid_)
if not c_:
continue
if c_.show not in ('offline', 'error'):
show_notif = False
break
if show_notif:
notify.notify('contact_connected', jid, account,
status)
elif obj.old_show > 1 and obj.new_show < 2:
show_notif = True
for c in lcontact:
if c.resource == resource:
# we look for other connected resources
continue
if c.show not in ('offline', 'error'):
show_notif = False
break
if show_notif:
# no other resource is connected, let's look in metacontacts
family = gajim.contacts.get_metacontacts_family(account,
jid)
for info in family:
acct_ = info['account']
jid_ = info['jid']
c_ = gajim.contacts.get_contact_with_highest_priority(
acct_, jid_)
if not c_:
continue
if c_.show not in ('offline', 'error'):
show_notif = False
break
if show_notif:
notify.notify('contact_disconnected', jid, account, status)
# Status change (not connected/disconnected or
# error (<1))
elif obj.new_show > 1:
notify.notify('status_change', jid, account, [obj.new_show,
status])
else:
# FIXME: MSN transport (CMSN1.2.1 and PyMSN) don't
# follow the XEP, still the case in 2008.
# It's maybe a GC_NOTIFY (specialy for MSN gc)
self.handle_event_gc_notify(account, (jid, show, status,
resource, None, None, None, None, None, [], None, None))
# It isn't an agent
# Notifications
obj.show_notif = True
for c in obj.contact_list:
if c.resource == resource:
# we look for other connected resources
continue
if c.show not in ('offline', 'error'):
obj.show_notif = False
break
if obj.show_notif:
# no other resource is connected, let's look in metacontacts
family = gajim.contacts.get_metacontacts_family(account,
jid)
for info in family:
acct_ = info['account']
jid_ = info['jid']
c_ = gajim.contacts.get_contact_with_highest_priority(
acct_, jid_)
if not c_:
continue
if c_.show not in ('offline', 'error'):
obj.show_notif = False
break
if show_notif:
if obj.old_show < 2 and obj.new_show > 1:
notify.notify('contact_connected', jid, account, status)
elif obj.old_show > 1 and obj.new_show < 2:
notify.notify('contact_disconnected', jid, account, status)
# Status change (not connected/disconnected or
# error (<1))
elif obj.new_show > 1:
notify.notify('status_change', jid, account, [obj.new_show,
status])
highest = gajim.contacts.get_contact_with_highest_priority(account, jid)
is_highest = (highest and highest.resource == resource)
# disconnect the session from the ctrl if the highest resource has
# changed
if (was_highest and not is_highest) or (not was_highest and is_highest):
if (obj.was_highest and not is_highest) or \
(not obj.was_highest and is_highest):
ctrl = self.msg_win_mgr.get_control(jid, account)
if ctrl:
ctrl.no_autonegotiation = False
ctrl.set_session(None)

View File

@ -62,6 +62,7 @@ from common.exceptions import GajimGeneralException
from common import i18n
from common import pep
from common import location_listener
from common import ged
from message_window import MessageWindowMgr
@ -1382,7 +1383,7 @@ class RosterWindow:
self.tree.set_model(None)
# disable sorting
self.model.set_sort_column_id(-2, gtk.SORT_ASCENDING)
def _after_fill(self):
self.model.set_sort_column_id(1, gtk.SORT_ASCENDING)
self.tree.set_model(self.modelfilter)
@ -1411,7 +1412,7 @@ class RosterWindow:
self._iters = {}
# for merged mode
self._iters['MERGED'] = {'account': None, 'groups': {}}
for acct in gajim.contacts.get_accounts():
self._iters[acct] = {'account': None, 'groups': {}, 'contacts': {}}
self.add_account(acct)
@ -2437,6 +2438,41 @@ class RosterWindow:
else:
on_continue('', None)
def _nec_presence_received(self, obj):
account = obj.conn.name
jid = obj.jid
if obj.need_add_in_roster:
self.add_contact(jid, account)
jid_list = gajim.contacts.get_jid_list(account)
if jid in jid_list or jid == gajim.get_jid_from_account(account):
if not gajim.jid_is_transport(jid) and len(obj.contact_list) == 1:
if obj.old_show == 0 and obj.new_show > 1:
gobject.timeout_add_seconds(5, self.remove_newly_added, jid,
account)
elif obj.old_show > 1 and obj.new_show == 0 and \
obj.conn.connected > 1:
gobject.timeout_add_seconds(5, self.remove_to_be_removed,
jid, account)
if obj.need_redraw:
self.draw_contact(jid, account)
if gajim.jid_is_transport(jid) and jid in jid_list:
# It must be an agent
# Update existing iter and group counting
self.draw_contact(jid, account)
self.draw_group(_('Transports'), account)
if obj.new_show > 1 and jid in gajim.transport_avatar[account]:
# transport just signed in.
# request avatars
for jid_ in gajim.transport_avatar[account][jid]:
obj.conn.request_vcard(jid_)
self.chg_contact_status(obj.contact, obj.show, obj.status, account)
################################################################################
### Menu and GUI callbacks
### FIXME: order callbacks in itself...
@ -6148,3 +6184,6 @@ class RosterWindow:
accel_group = gtk.accel_groups_from_object(self.window)[0]
accel_group.connect_group(gtk.keysyms.j, gtk.gdk.CONTROL_MASK,
gtk.ACCEL_MASK, self.on_ctrl_j)
gajim.ged.register_event_handler('presence-received', ged.GUI1,
self._nec_presence_received)