14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
from gi.repository import Gtk
18
from gi.repository import GdkPixbuf
20
19
from bzrlib.config import parse_username
22
from bzrlib.plugins.gtk.i18n import _i18n
21
from bzrlib.plugins.gtk import _i18n
23
22
from bzrlib.plugins.gtk.avatarproviders import (
24
23
AvatarProviderGravatar,
25
24
AvatarDownloaderWorker,
29
class Avatar(Gtk.HBox):
28
class Avatar(gtk.HBox):
30
29
""" Author or committer avatar """
32
31
def __init__(self, apparent_username):
33
32
""" Constructor """
34
super(Avatar, self).__init__()
33
gtk.HBox.__init__(self)
36
35
self.apparent_username = apparent_username
37
36
self.username, self.email = parse_username(apparent_username)
40
39
def __eq__(self, other):
41
40
return (self.apparent_username == other.apparent_username and
42
self.username == other.username and
41
self.name == other.name and
43
42
self.email == other.email)
45
44
def show_spinner(self):
47
Replace the current content of the Avatar with a Gtk.Spinner
48
if an email address has been parsed. If not, show an Gtk.Label with
46
Replace the current content of the Avatar with a gtk.Spinner
47
if an email address has been parsed. If not, show an gtk.Label with
49
48
the translatable 'No email' text.
52
tooltip = _i18n("Retrieving avatar for %s...") % self.email
53
spinner = Gtk.Spinner()
51
spinner = gtk.Spinner()
55
self.pack_start(spinner, False, True, 0)
56
spinner.set_tooltip_text(tooltip)
53
self.pack_start(spinner, False)
54
spinner.set_tooltip_text(_i18n("Retrieving avatar for %s...") % self.email)
57
55
spinner.set_size_request(20, 20)
60
no_email = Gtk.Label(label=_i18n("No email"))
61
self.pack_start(no_email, True, True, 0)
58
no_email = gtk.Label(_i18n("No email"))
59
self.pack_start(no_email)
62
60
self.set_tooltip_text(self.apparent_username)
65
63
def show_image(self):
66
"""Replace the current content of the Avatar with the Gtk.Image """
64
"""Replace the current content of the Avatar with the gtk.Image """
67
65
if self.email and self.image:
68
children = self.get_children()
70
self.remove(children[0])
71
self.pack_start(self.image, True, True, 0)
66
self.remove(self.get_children()[0])
67
self.pack_start(self.image)
72
68
self.image.set_tooltip_text(self.apparent_username)
76
class AvatarBox(Gtk.HBox):
72
class AvatarBox(gtk.HBox):
77
73
"""HBox showing an avatar."""
79
75
def __init__(self, homogeneous=False, spacing=0):
80
super(AvatarBox, self).__init__(
81
homogeneous=homogeneous, spacing=spacing)
76
gtk.HBox.__init__(self, homogeneous, spacing)
82
77
self.__avatars = {}
84
79
self.__displaying = None
129
124
def update_avatar_image_from_pixbuf_loader(self, loader):
130
"""Replace the Gtk.Spinner with the given loader."""
125
"""Replace the gtk.Spinner with the given loader."""
132
self.avatar.image = Gtk.Image()
127
self.avatar.image = gtk.Image()
133
128
self.avatar.image.set_from_pixbuf(loader.get_pixbuf())
134
129
self.avatar.show_image()
135
130
self.__displaying = self.avatar
137
132
def come_back_to_gui(self):
138
133
"""Render back avatar in the GUI."""
140
self.pack_start(self.avatar, True, True, 0)
135
self.pack_start(self.avatar)
141
136
self.__displaying = self.avatar
143
138
self._show_no_email()
145
140
def _new_cell_for_avatar(self, avatar):
146
"""Create a new cell in this box with a Gtk.Spinner."""
141
"""Create a new cell in this box with a gtk.Spinner."""
147
142
avatar.show_spinner()
148
self.pack_start(avatar, True, True, 0)
143
self.pack_start(avatar)
150
145
self.__displaying = avatar
152
147
def _show_no_email(self):
153
"""Show a Gtk.Label with text 'No email'."""
154
no_email = Gtk.Label(label=_i18n("No email"))
155
self.pack_start(no_email, True, True, 0)
148
"""Show a gtk.Label with test 'No email'."""
149
no_email = gtk.Label(_i18n("No email"))
150
self.pack_start(no_email)
159
class AvatarsBox(Gtk.HBox):
154
class AvatarsBox(gtk.HBox):
160
155
"""GTK container for author and committer avatars."""
162
157
def __init__(self):
163
super(AvatarsBox, self).__init__(homogeneous=False, spacing=10)
158
gtk.HBox.__init__(self, False, 10)
164
160
self.__committer_box = None
165
161
self.__authors_box = None
181
177
# This callback method should be fired by all workers when a request
183
179
self.__worker.set_callback_method(self._update_avatar_from_response)
184
self.connect('destroy', self.on_destroy)
186
def on_destroy(self, widget):
188
if self.__worker.is_alive():
180
self.__worker.start()
191
182
def add(self, username, role):
192
183
"""Add the given username in the role box and add in the worker queue.
194
185
avatar = Avatar(username)
195
is_shown = self._role_box_for("committer").showing(avatar)
196
if (role == "author" and not is_shown) or role == "committer":
186
if (role == "author" and not self._role_box_for("committer").showing(avatar)) or role == "committer":
197
187
if self._role_box_for(role).append_avatars_with(avatar):
198
188
self.__worker.queue(avatar.email)
213
203
def _init_gui(self):
214
204
"""Create boxes where avatars will be displayed."""
215
# 2 Gtk.HBox: One for the committer and one for authors
205
# 2 gtk.HBox: One for the committer and one for authors
217
207
self.__committer_box = AvatarBox()
218
208
self.__committer_box.set_size_request(80, 80)
219
self.pack_end(self.__committer_box, False, True, 0)
209
self.pack_end(self.__committer_box, False)
220
210
self.__committer_box.show()
222
212
self.__authors_box = AvatarBox()
223
self.pack_end(self.__authors_box, False, True, 0)
213
self.pack_end(self.__authors_box, False)
224
214
self.__authors_box.set_spacing(10)
225
215
self.__authors_box.show()
231
221
:param email: used to identify item from self.__avatars.
234
# Convert downloaded image from provider to Gtk.Image
235
loader = GdkPixbuf.PixbufLoader()
224
# Convert downloaded image from provider to gtk.Image
225
loader = gtk.gdk.PixbufLoader()
236
226
loader.write(response.read())
239
229
for role in ["committer", "author"]:
240
self._role_box_for(role).and_avatar_email(
241
email).update_avatar_image_from_pixbuf_loader(loader)
230
self._role_box_for(role).and_avatar_email(email).update_avatar_image_from_pixbuf_loader(loader)
243
232
def _role_box_for(self, role):
244
""" Return the Gtk.HBox for the given role """
233
""" Return the gtk.HBox for the given role """
245
234
if role == "committer":
246
235
return self.__committer_box