#!/usr/bin/env python # -*- coding: utf-8 -*- # Mitter, a micro-blogging client with multiple interfaces. # Copyright (C) 2007-2010 Mitter Contributors # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import logging import urllib2 import gtk # ---------------------------------------------------------------------- # Constants # ---------------------------------------------------------------------- _log = logging.getLogger('ui.helpers.avatarcache') # ---------------------------------------------------------------------- # The cache class # ---------------------------------------------------------------------- class AvatarCache(object): """An avatar cache, storing GDK pixbufs references.""" def __init__(self, connection, default, timeout=None): """Initialization of the cache. connection: A :class:`ThreadManager`, which will be used as thread pool to request the avatars. default: A gdk_pixbuf to be used as placeholder while the real avatar is being downloaded. timeout: Request timeout when downloading the avatars.""" self._connection = connection self._default = default self._cache = {} self._timeout = timeout def get(self, owner, avatar, url=None): """Return the avatar from the cache or, if the avatar isn't available yet, returns the default avatar and queue the download of it. owner: The object requesting the avatar. Must have a "queue_draw()" method, which will be called once the avatar is available. Can be None. avatar: The identification of the avatar. Can be any string. url: URL to download the avatar. If not passed, *avatar* **must** be a valid URL.""" if avatar in self._cache: return self._cache[avatar] if not url: url = avatar self._connection.add_work(self._post_avatar_download, self._exception_avatar_download, self._download_pic, avatar, url, owner) # add the default avatar in the cache just to avoid a new request for # it. It will be overwritten anyway later. self._cache[avatar] = self._default return self._default # ------------------------------------------------------------ # Network functions # ------------------------------------------------------------ def _download_pic(self, avatar, url, owner): """Download a picture from the web. Can be used in a thread.""" request = urllib2.Request(url=url) timeout = self._timeout _log.debug('Starting request of %s (timeout %ds)' % ( url, timeout)) try: response = urllib2.urlopen(request, timeout=timeout) except TypeError, e: # Python 2.5 doesn't have a timeout parameter response = urllib2.urlopen(request) data = response.read() _log.debug('Request completed') return (avatar, owner, data) def _post_avatar_download(self, widget, data): """Called after the data from the picture is available.""" (avatar, owner, data) = data loader = gtk.gdk.PixbufLoader() loader.write(data) loader.close() user_pic = loader.get_pixbuf() user_pic = user_pic.scale_simple(48, 48, gtk.gdk.INTERP_BILINEAR) self._cache[avatar] = user_pic if owner: owner.queue_draw() return def _exception_avatar_download(self, widget, exception): """Called in case we have a problem downloading an user avatar.""" _log.debug('Exception trying to get an avatar.') _log.debug(str(exception)) return