A micro-blogging tool with multiple interfaces.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

124 lines
4.2 KiB

#!/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 <http://www.gnu.org/licenses/>.
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))
response = urllib2.urlopen(request, timeout=timeout)
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