core: make getcwd() fail-safe
[git-cola.git] / cola / gravatar.py
blob00a7ae5a5952ce82d02abe07329c126d49becb6c
1 from __future__ import division, absolute_import, unicode_literals
2 import time
3 import hashlib
5 from qtpy import QtCore
6 from qtpy import QtGui
7 from qtpy import QtWidgets
8 from qtpy import QtNetwork
10 from . import core
11 from . import icons
12 from .compat import bstr
13 from .compat import ustr
14 from .compat import parse
15 from .widgets import defs
18 class Gravatar(object):
20 @staticmethod
21 def url_for_email(email, imgsize):
22 email_hash = core.decode(hashlib.md5(core.encode(email)).hexdigest())
23 # Python2.6 requires byte strings for urllib2.quote() so we have
24 # to force
25 default_url = 'https://git-cola.github.io/images/git-64x64.jpg'
26 encoded_url = parse.quote(core.encode(default_url), core.encode(''))
27 query = '?s=%d&d=%s' % (imgsize, core.decode(encoded_url))
28 url = 'https://gravatar.com/avatar/' + email_hash + query
29 return url
32 class GravatarLabel(QtWidgets.QLabel):
34 def __init__(self, parent=None):
35 QtWidgets.QLabel.__init__(self, parent)
37 self.email = None
38 self.response = None
39 self.timeout = 0
40 self.imgsize = defs.medium_icon
41 self.pixmaps = {}
42 self._default_pixmap_bytes = None
44 self.network = QtNetwork.QNetworkAccessManager()
45 self.network.finished.connect(self.network_finished)
47 def set_email(self, email):
48 if email in self.pixmaps:
49 self.setPixmap(self.pixmaps[email])
50 return
51 if (self.timeout > 0 and
52 (int(time.time()) - self.timeout) < (5 * 60)):
53 self.set_pixmap_from_response()
54 return
55 if email == self.email and self.response is not None:
56 self.set_pixmap_from_response()
57 return
58 self.email = email
59 self.request(email)
61 def request(self, email):
62 url = Gravatar.url_for_email(email, self.imgsize)
63 self.network.get(QtNetwork.QNetworkRequest(QtCore.QUrl(url)))
65 def default_pixmap_as_bytes(self):
66 if self._default_pixmap_bytes is None:
67 xres = self.imgsize
68 pixmap = icons.cola().pixmap(xres)
69 byte_array = QtCore.QByteArray()
70 buf = QtCore.QBuffer(byte_array)
71 buf.open(QtCore.QIODevice.WriteOnly)
72 pixmap.save(buf, 'PNG')
73 buf.close()
74 self._default_pixmap_bytes = byte_array
75 else:
76 byte_array = self._default_pixmap_bytes
77 return byte_array
79 def network_finished(self, reply):
80 email = self.email
82 header = QtCore.QByteArray(bstr('Location'))
83 location = ustr(reply.rawHeader(header)).strip()
84 if location:
85 request_location = Gravatar.url_for_email(self.email, self.imgsize)
86 relocated = location != request_location
87 else:
88 relocated = False
90 if reply.error() == QtNetwork.QNetworkReply.NoError:
91 if relocated:
92 # We could do get_url(parse.unquote(location)) to
93 # download the default image.
94 # Save bandwidth by using a pixmap.
95 self.response = self.default_pixmap_as_bytes()
96 else:
97 self.response = reply.readAll()
98 self.timeout = 0
99 else:
100 self.response = self.default_pixmap_as_bytes()
101 self.timeout = int(time.time())
103 pixmap = self.set_pixmap_from_response()
105 # If the email has not changed (e.g. no other requests)
106 # then we know that this pixmap corresponds to this specific
107 # email address. We can't blindly trust self.email else
108 # we may add cache entries for thee wrong email address.
109 url = Gravatar.url_for_email(email, self.imgsize)
110 if url == reply.url().toString():
111 self.pixmaps[email] = pixmap
113 def set_pixmap_from_response(self):
114 if self.response is None:
115 self.response = self._default_pixmap_bytes()
116 pixmap = QtGui.QPixmap()
117 pixmap.loadFromData(self.response)
118 self.setPixmap(pixmap)
119 return pixmap