we now cache avatar, so we only ask once. TODO: ask, store and show in roster; TODO2: on new sha reask vcard to get new avatar

This commit is contained in:
Nikos Kouremenos 2005-10-03 16:14:41 +00:00
parent 7518d20bf7
commit 6899985d5c
3 changed files with 102 additions and 67 deletions

View File

@ -66,11 +66,13 @@ import gtkexcepthook
import gobject import gobject
if sys.version[:4] >= '2.4': if sys.version[:4] >= '2.4':
gobject.threads_init() gobject.threads_init()
import pango import pango
import sre import sre
import signal import signal
import getopt import getopt
import time import time
import base64
from common import socks5 from common import socks5
import gtkgui_helpers import gtkgui_helpers
@ -621,29 +623,30 @@ class Interface:
win = self.windows[account]['infos'][array['jid']] win = self.windows[account]['infos'][array['jid']]
win.set_values(array) win.set_values(array)
def handle_event_vcard(self, account, array): def handle_event_vcard(self, account, vcard):
'''vcard holds the vcard data'''
jid = vcard['jid']
self.store_avatar(vcard)
# vcard window
win = None win = None
if self.windows[account]['infos'].has_key(array['jid']): if self.windows[account]['infos'].has_key(jid):
win = self.windows[account]['infos'][array['jid']] win = self.windows[account]['infos'][jid]
elif self.windows[account]['infos'].has_key(array['jid'] + '/' + \ elif self.windows[account]['infos'].has_key(jid + '/' +vcard['resource']):
array['resource']): win = self.windows[account]['infos'][jid + '/' + vcard['resource']]
win = self.windows[account]['infos'][array['jid'] + '/' + \
array['resource']]
if win: if win:
win.set_values(array) win.set_values(vcard) #FIXME: maybe store all vcard data?
# show avatar in chat # show avatar in chat
win = None win = None
if self.windows[account]['chats'].has_key(array['jid']): if self.windows[account]['chats'].has_key(jid):
win = self.windows[account]['chats'][array['jid']] win = self.windows[account]['chats'][jid]
elif self.windows[account]['chats'].has_key(array['jid'] + '/' + \ elif self.windows[account]['chats'].has_key(jid + '/' +vcard['resource']):
array['resource']): win = self.windows[account]['chats'][jid + '/' + vcard['resource']]
win = self.windows[account]['chats'][array['jid'] + '/' + \
array['resource']]
if win: if win:
win.set_avatar(array) win.show_avatar(jid)
if self.remote is not None: if self.remote is not None:
self.remote.raise_signal('VcardInfo', (account, array)) self.remote.raise_signal('VcardInfo', (account, vcard))
def handle_event_os_info(self, account, array): def handle_event_os_info(self, account, array):
win = None win = None
@ -863,6 +866,42 @@ class Interface:
def handle_event_vcard_not_published(self, account, array): def handle_event_vcard_not_published(self, account, array):
dialogs.InformationDialog(_('vCard publication failed'), _('There was an error while publishing your personal information, try again later.')) dialogs.InformationDialog(_('vCard publication failed'), _('There was an error while publishing your personal information, try again later.'))
def store_avatar(self, vcard):
'''stores avatar per jid so we do not have to ask everytime for vcard'''
jid = vcard['jid']
# we assume contact has no avatar
self.avatar_pixbufs[jid] = None
if not vcard.has_key('PHOTO'):
return
if not isinstance(vcard['PHOTO'], dict):
return
img_decoded = None
if vcard['PHOTO'].has_key('BINVAL'):
try:
img_decoded = base64.decodestring(vcard['PHOTO']['BINVAL'])
except:
pass
elif vcard['PHOTO'].has_key('EXTVAL'):
url = vcard['PHOTO']['EXTVAL']
try:
fd = urllib.urlopen(url)
img_decoded = fd.read()
except:
pass
if img_decoded:
pixbufloader = gtk.gdk.PixbufLoader()
try:
pixbufloader.write(img_decoded)
pixbuf = pixbufloader.get_pixbuf()
pixbufloader.close()
# store avatar for jid
self.avatar_pixbufs[jid] = pixbuf
# we may get "unknown image format" and/or something like pixbuf can be None
except (gobject.GError, AttributeError):
pass
def read_sleepy(self): def read_sleepy(self):
'''Check idle status and change that status if needed''' '''Check idle status and change that status if needed'''
if not self.sleeper.poll(): if not self.sleeper.poll():
@ -1121,6 +1160,7 @@ class Interface:
'outmsgcolor': gajim.config.get('outmsgcolor'), 'outmsgcolor': gajim.config.get('outmsgcolor'),
'statusmsgcolor': gajim.config.get('statusmsgcolor'), 'statusmsgcolor': gajim.config.get('statusmsgcolor'),
} }
parser.read() parser.read()
# Do not set gajim.verbose to False if -v option was given # Do not set gajim.verbose to False if -v option was given
if gajim.config.get('verbose'): if gajim.config.get('verbose'):
@ -1172,8 +1212,12 @@ class Interface:
gtk.about_dialog_set_email_hook(self.on_launch_browser_mailer, 'mail') gtk.about_dialog_set_email_hook(self.on_launch_browser_mailer, 'mail')
gtk.about_dialog_set_url_hook(self.on_launch_browser_mailer, 'url') gtk.about_dialog_set_url_hook(self.on_launch_browser_mailer, 'url')
self.windows = {'logs': {}} self.windows = {'logs': {}}
# keep avatar (pixbuf) per jid
self.avatar_pixbufs = {}
for a in gajim.connections: for a in gajim.connections:
self.windows[a] = {'infos': {}, 'chats': {}, 'gc': {}, 'gc_config': {}} self.windows[a] = {'infos': {}, 'chats': {}, 'gc': {}, 'gc_config': {}}
gajim.contacts[a] = {} gajim.contacts[a] = {}

View File

@ -58,8 +58,9 @@ class TabbedChatWindow(chat.Chat):
self.show_bigger_avatar_timeout_id = None self.show_bigger_avatar_timeout_id = None
self.bigger_avatar_window = None self.bigger_avatar_window = None
# keep avatar (pixbuf) per jid. FIXME: move this when we cache avatars # list that holds all the jid we have asked vcard once
self.avatar_pixbufs = {} # (so we do not have to ask again)
self.jids_for_which_we_asked_vcard_already = list()
self.TARGET_TYPE_URI_LIST = 80 self.TARGET_TYPE_URI_LIST = 80
self.dnd_list = [ ( 'text/uri-list', 0, self.TARGET_TYPE_URI_LIST ) ] self.dnd_list = [ ( 'text/uri-list', 0, self.TARGET_TYPE_URI_LIST ) ]
@ -221,51 +222,30 @@ timestamp, contact):
def get_specific_unread(self, jid): def get_specific_unread(self, jid):
return 0 # FIXME: always zero why?? return 0 # FIXME: always zero why??
def set_avatar(self, vcard): def show_avatar(self, jid):
if not vcard.has_key('PHOTO'): assert(not self.plugin.avatar_pixbufs.has_key(jid))
return if not self.plugin.avatar_pixbufs.has_key(jid) or\
if not isinstance(vcard['PHOTO'], dict): self.plugin.avatar_pixbufs[jid] is None:
return return # contact does not have avatar stored (can this happen?) or has no avatar
img_decoded = None
if vcard['PHOTO'].has_key('BINVAL'):
try:
img_decoded = base64.decodestring(vcard['PHOTO']['BINVAL'])
except:
pass
elif vcard['PHOTO'].has_key('EXTVAL'):
url = vcard['PHOTO']['EXTVAL']
try:
fd = urllib.urlopen(url)
img_decoded = fd.read()
except:
pass
if img_decoded:
pixbufloader = gtk.gdk.PixbufLoader()
try:
pixbufloader.write(img_decoded)
pixbuf = pixbufloader.get_pixbuf()
pixbufloader.close()
jid = vcard['jid']
self.avatar_pixbufs[jid] = pixbuf
pixbuf = self.plugin.avatar_pixbufs[jid]
w = gajim.config.get('avatar_width') w = gajim.config.get('avatar_width')
h = gajim.config.get('avatar_height') h = gajim.config.get('avatar_height')
scaled_buf = pixbuf.scale_simple(w, h, gtk.gdk.INTERP_HYPER) scaled_buf = pixbuf.scale_simple(w, h, gtk.gdk.INTERP_HYPER)
x = None x = None
if self.xmls.has_key(jid): if self.xmls.has_key(jid):
x = self.xmls[jid] x = self.xmls[jid]
else:
# it can be xmls[jid/resource] if it's a vcard from pm # it can be xmls[jid/resource] if it's a vcard from pm
elif self.xmls.has_key(jid + '/' + vcard['resource']): jid_with_resource = jid + '/' + vcard['resource']
x = self.xmls[jid + '/' + vcard['resource']] if self.xmls.has_key(jid_with_resource):
x = self.xmls[jid_with_resource]
if x is not None:
image = x.get_widget('avatar_image') image = x.get_widget('avatar_image')
image.set_from_pixbuf(scaled_buf) image.set_from_pixbuf(scaled_buf)
image.show_all() image.show_all()
# we may get "unknown image format" and/or something like pixbuf can be None
except (gobject.GError, AttributeError):
pass
def set_state_image(self, jid): def set_state_image(self, jid):
prio = 0 prio = 0
@ -399,6 +379,18 @@ timestamp, contact):
self.childs[contact.jid] = self.xmls[contact.jid].get_widget('chats_vbox') self.childs[contact.jid] = self.xmls[contact.jid].get_widget('chats_vbox')
self.contacts[contact.jid] = contact self.contacts[contact.jid] = contact
#FIXME: request in thread or idle and show in roster
# this is to prove cache code works:
# should we ask vcard? (only the first time we should ask)
if not self.plugin.avatar_pixbufs.has_key(contact.jid):
# it's the first time, so we should ask vcard
gajim.connections[self.account].request_vcard(contact.jid)
#please do not remove this commented print until I'm done with showing
#avatars in roster
#print 'REQUESTING VCARD for', contact.jid
else:
self.show_avatar(contact.jid) # show avatar from stored place
self.childs[contact.jid].connect('drag_data_received', self.childs[contact.jid].connect('drag_data_received',
self.on_drag_data_received, contact) self.on_drag_data_received, contact)
@ -428,7 +420,6 @@ timestamp, contact):
if gajim.awaiting_messages[self.account].has_key(contact.jid): if gajim.awaiting_messages[self.account].has_key(contact.jid):
self.read_queue(contact.jid) self.read_queue(contact.jid)
gajim.connections[self.account].request_vcard(contact.jid)
self.childs[contact.jid].show_all() self.childs[contact.jid].show_all()
# chatstates # chatstates