Handle loading of images with a thread.

See #5892.
Fix #5331.
This commit is contained in:
Julien Pivotto 2011-03-23 14:07:58 +01:00
parent d5d3cd0fd3
commit 39434dfe1e
1 changed files with 35 additions and 12 deletions

View File

@ -53,6 +53,7 @@ if __name__ == '__main__':
common.configpaths.gajimpaths.init(None) common.configpaths.gajimpaths.init(None)
import gtkgui_helpers import gtkgui_helpers
from common import gajim from common import gajim
from gtkgui_helpers import get_icon_pixmap
import tooltips import tooltips
import logging import logging
@ -485,7 +486,7 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
return tag return tag
def _get_img(self, attrs): def _get_img(self, attrs):
mem = '' mem, alt = '', ''
# Wait maximum 1s for connection # Wait maximum 1s for connection
socket.setdefaulttimeout(1) socket.setdefaulttimeout(1)
try: try:
@ -534,21 +535,34 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
alt += '\n' alt += '\n'
alt += _('Image is too big') alt += _('Image is too big')
break break
return mem return (mem, alt)
def _process_img(self, attrs): def _update_img(self, (mem, alt), attrs, img_mark):
self._process_img(attrs, (mem, alt, img_mark))
def _process_img(self, attrs, loaded=None):
'''Process a img tag. '''Process a img tag.
''' '''
mem = '' mem = ''
update = False
pixbuf = None
replace_mark = None
try: try:
if attrs['src'].startswith('data:image/'): if attrs['src'].startswith('data:image/'):
# The "data" URL scheme http://tools.ietf.org/html/rfc2397 # The "data" URL scheme http://tools.ietf.org/html/rfc2397
import base64 import base64
img = attrs['src'].split(',')[1] img = attrs['src'].split(',')[1]
mem = base64.standard_b64decode(urllib2.unquote(img)) mem = base64.standard_b64decode(urllib2.unquote(img))
elif loaded is not None:
(mem, alt, replace_mark) = loaded
update = True
else: else:
mem = self._get_img(attrs) img_mark = self.textbuf.create_mark(None, self.iter, True)
pixbuf = None gajim.thread_interface(self._get_img, [attrs], \
self._update_img, [attrs, img_mark])
alt = 'Loading...'
pixbuf = get_icon_pixmap('gajim-receipt_missing')
if mem: if mem:
# Caveat: GdkPixbuf is known not to be safe to load # Caveat: GdkPixbuf is known not to be safe to load
# images from network... this program is now potentially # images from network... this program is now potentially
@ -593,19 +607,26 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
loader.close() loader.close()
pixbuf = loader.get_pixbuf() pixbuf = loader.get_pixbuf()
alt = attrs.get('alt', '') alt = attrs.get('alt', '')
working_iter = self.iter
if replace_mark is not None:
working_iter = self.textbuf.get_iter_at_mark(replace_mark)
next_iter = working_iter.copy()
next_iter.forward_char()
self.textbuf.delete(working_iter, next_iter)
self.textbuf.delete_mark(replace_mark)
if pixbuf is not None: if pixbuf is not None:
tags = self._get_style_tags() tags = self._get_style_tags()
if tags: if tags:
tmpmark = self.textbuf.create_mark(None, self.iter, True) tmpmark = self.textbuf.create_mark(None, working_iter, True)
self.textbuf.insert_pixbuf(self.iter, pixbuf) self.textbuf.insert_pixbuf(working_iter, pixbuf)
self.starting = False self.starting = False
if tags: if tags:
start = self.textbuf.get_iter_at_mark(tmpmark) start = self.textbuf.get_iter_at_mark(tmpmark)
for tag in tags: for tag in tags:
self.textbuf.apply_tag(tag, start, self.iter) self.textbuf.apply_tag(tag, start, working_iter)
self.textbuf.delete_mark(tmpmark) self.textbuf.delete_mark(tmpmark)
else: else:
self._insert_text('[IMG: %s]' % alt) self._insert_text('[IMG: %s]' % alt, working_iter)
except Exception, ex: except Exception, ex:
log.error('Error loading image ' + str(ex)) log.error('Error loading image ' + str(ex))
pixbuf = None pixbuf = None
@ -644,14 +665,16 @@ class HtmlHandler(xml.sax.handler.ContentHandler):
self.textbuf.insert_with_tags_by_name(self.iter, '\n', 'eol') self.textbuf.insert_with_tags_by_name(self.iter, '\n', 'eol')
self.starting = True self.starting = True
def _insert_text(self, text): def _insert_text(self, text, working_iter=None):
if working_iter == None:
working_iter = self.iter
if self.starting and text != '\n': if self.starting and text != '\n':
self.starting = (text[-1] == '\n') self.starting = (text[-1] == '\n')
tags = self._get_style_tags() tags = self._get_style_tags()
if tags: if tags:
self.textbuf.insert_with_tags(self.iter, text, *tags) self.textbuf.insert_with_tags(working_iter, text, *tags)
else: else:
self.textbuf.insert(self.iter, text) self.textbuf.insert(working_iter, text)
def _starts_line(self): def _starts_line(self):
return self.starting or self.iter.starts_line() return self.starting or self.iter.starts_line()