/b-gtk/fix-viz

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/b-gtk/fix-viz
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
1
# Copyright (C) 2011 by Guillaume Hain (zedtux) <zedtux@zedroot.org>
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
17
from gi.repository import Gtk
734.1.25 by Curtis Hovey
Updated the pixbuf calls to gtk3.
18
from gi.repository import GdkPixbuf
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
19
723 by Jelmer Vernooij
Merge support for showing gravatars.
20
from bzrlib.config import parse_username
21
729.1.1 by Jelmer Vernooij
Move i18n support to a separate file, so gettext files aren't loaded unless bzr-gtk is used.
22
from bzrlib.plugins.gtk.i18n import _i18n
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
23
from bzrlib.plugins.gtk.avatarproviders import (
24
    AvatarProviderGravatar,
25
    AvatarDownloaderWorker,
26
    )
27
28
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
29
class Avatar(Gtk.HBox):
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
30
    """ Author or committer avatar """
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
31
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
32
    def __init__(self, apparent_username):
33
        """ Constructor """
734.1.6 by Curtis Hovey
Added a very rough fix to see gannontation.
34
        Gtk.HBox.__init__(self)
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
35
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
36
        self.apparent_username = apparent_username
37
        self.username, self.email = parse_username(apparent_username)
38
        self.image = None
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
39
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
40
    def __eq__(self, other):
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
41
        return (self.apparent_username == other.apparent_username and
734.1.6 by Curtis Hovey
Added a very rough fix to see gannontation.
42
                self.username == other.username and
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
43
                self.email == other.email)
44
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
45
    def show_spinner(self):
46
        """
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
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
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
49
        the translatable 'No email' text.
50
        """
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
51
        if self.email:
729 by Jelmer Vernooij
Support use without gtk.Spinner, which is only available in pygtk >= 2.22.
52
            tooltip = _i18n("Retrieving avatar for %s...") % self.email
734.1.6 by Curtis Hovey
Added a very rough fix to see gannontation.
53
            spinner = Gtk.Spinner()
54
            spinner.start()
55
            self.pack_start(spinner, False, True, 0)
56
            spinner.set_tooltip_text(tooltip)
57
            spinner.set_size_request(20, 20)
58
            spinner.show()
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
59
        else:
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
60
            no_email = Gtk.Label(label=_i18n("No email"))
61
            self.pack_start(no_email, True, True, 0)
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
62
            self.set_tooltip_text(self.apparent_username)
63
            no_email.show()
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
64
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
65
    def show_image(self):
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
66
        """Replace the current content of the Avatar with the Gtk.Image """
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
67
        if self.email and self.image:
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
68
            self.remove(self.get_children()[0])
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
69
            self.pack_start(self.image, True, True, 0)
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
70
            self.image.set_tooltip_text(self.apparent_username)
71
            self.image.show()
72
73
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
74
class AvatarBox(Gtk.HBox):
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
75
    """HBox showing an avatar."""
76
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
77
    def __init__(self, homogeneous=False, spacing=0):
734.1.6 by Curtis Hovey
Added a very rough fix to see gannontation.
78
        Gtk.HBox.__init__(self, homogeneous=homogeneous, spacing=spacing)
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
79
        self.__avatars = {}
80
        self.avatar = None
81
        self.__displaying = None
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
82
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
83
    def reset_view(self):
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
84
        """Remove current avatars from the gtk box."""
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
85
        for child in self.get_children():
86
            self.remove(child)
87
        self.__displaying = None
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
88
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
89
    def have_avatar(self, avatar):
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
90
        """Return True if this box has the specified avatar.
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
91
        """
92
        return avatar.email in self.__avatars
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
93
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
94
    def showing(self, avatar):
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
95
        """Return True if the displaying avatar matches the specified one.
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
96
        """
97
        return self.__displaying and self.__displaying == avatar
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
98
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
99
    def append_avatars_with(self, avatar):
100
        """
101
        Append avatars collection with the given one if not already registed
102
        otherwise render it back.
103
        When an avatar is added this method True, otherwise, if the avatar
104
        was in the collection, return False.
105
        """
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
106
        if avatar.email and not avatar.email in self.__avatars:
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
107
            self.__avatars[avatar.email] = avatar
108
            self._new_cell_for_avatar(avatar)
109
            return True
110
        else:
111
            self.and_avatar_email(avatar.email).come_back_to_gui()
112
        return False
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
113
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
114
    def and_avatar_email(self, email):
115
        """
116
        Select the avatar from avatars collection
117
        in order to apply future actions
118
        """
119
        self.avatar = None
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
120
        if email and email in self.__avatars:
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
121
            self.avatar = self.__avatars[email]
122
        else:
123
            self.avatar = None
124
        return self
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
125
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
126
    def update_avatar_image_from_pixbuf_loader(self, loader):
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
127
        """Replace the Gtk.Spinner with the given loader."""
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
128
        if self.avatar:
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
129
            self.avatar.image = Gtk.Image()
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
130
            self.avatar.image.set_from_pixbuf(loader.get_pixbuf())
131
            self.avatar.show_image()
132
            self.__displaying = self.avatar
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
133
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
134
    def come_back_to_gui(self):
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
135
        """Render back avatar in the GUI."""
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
136
        if self.avatar:
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
137
            self.pack_start(self.avatar, True, True, 0)
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
138
            self.__displaying = self.avatar
139
        else:
140
            self._show_no_email()
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
141
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
142
    def _new_cell_for_avatar(self, avatar):
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
143
        """Create a new cell in this box with a Gtk.Spinner."""
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
144
        avatar.show_spinner()
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
145
        self.pack_start(avatar, True, True, 0)
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
146
        avatar.show()
147
        self.__displaying = avatar
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
148
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
149
    def _show_no_email(self):
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
150
        """Show a Gtk.Label with test 'No email'."""
151
        no_email = Gtk.Label(label=_i18n("No email"))
152
        self.pack_start(no_email, True, True, 0)
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
153
        no_email.show()
154
155
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
156
class AvatarsBox(Gtk.HBox):
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
157
    """GTK container for author and committer avatars."""
158
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
159
    def __init__(self):
734.1.6 by Curtis Hovey
Added a very rough fix to see gannontation.
160
        Gtk.HBox.__init__(self, homogeneous=False, spacing=10)
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
161
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
162
        self.__committer_box = None
163
        self.__authors_box = None
164
        self._init_gui()
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
165
166
        # If more later you want to implement more avatar providers:
167
        # * Create a new class named AvatarProvider + provider_name that
168
        #   inherit from the AvatarProvider class.
169
        # * Implement a method that return url to use in the request.
170
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
171
        # For example, with Gravatar, the method return the complete url
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
172
        # with MD5 hash of the email address and put the value in a
173
        # gravatar_id field.
174
        # Then create a new worker (manage them in a python dictionary).
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
175
        provider = AvatarProviderGravatar()
176
        self.__worker = AvatarDownloaderWorker(
177
            provider.gravatar_id_for_email
178
        )
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
179
        # This callback method should be fired by all workers when a request
180
        # is done.
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
181
        self.__worker.set_callback_method(self._update_avatar_from_response)
182
        self.__worker.start()
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
183
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
184
    def add(self, username, role):
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
185
        """Add the given username in the role box and add in the worker queue.
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
186
        """
187
        avatar = Avatar(username)
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
188
        if (role == "author" and not self._role_box_for("committer").showing(avatar)) or role == "committer":
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
189
            if self._role_box_for(role).append_avatars_with(avatar):
190
                self.__worker.queue(avatar.email)
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
191
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
192
    def merge(self, usernames, role):
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
193
        """Add avatars from a list"""
719.2.2 by zedtux
Patched code following Jelmer's recommandations
194
        for username in usernames:
195
            self.add(username, role)
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
196
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
197
    def reset(self):
198
        """
199
        Request a reset view for all boxes in order to show only avatars
200
        of the selected line in the revision view screen.
201
        """
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
202
        for role in ("committer", "author"):
203
            self._role_box_for(role).reset_view()
204
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
205
    def _init_gui(self):
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
206
        """Create boxes where avatars will be displayed."""
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
207
        # 2 Gtk.HBox: One for the committer and one for authors
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
208
        # Committer
209
        self.__committer_box = AvatarBox()
210
        self.__committer_box.set_size_request(80, 80)
734.1.6 by Curtis Hovey
Added a very rough fix to see gannontation.
211
        self.pack_end(self.__committer_box, False, True, 0)
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
212
        self.__committer_box.show()
213
        # Authors
214
        self.__authors_box = AvatarBox()
734.1.6 by Curtis Hovey
Added a very rough fix to see gannontation.
215
        self.pack_end(self.__authors_box, False, True, 0)
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
216
        self.__authors_box.set_spacing(10)
217
        self.__authors_box.show()
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
218
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
219
    def _update_avatar_from_response(self, response, email):
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
220
        """Callback method fired by avatar worker when finished.
221
222
        :param response: a urllib2.urlopen() return value.
223
        :param email: used to identify item from self.__avatars.
224
        """
734.1.25 by Curtis Hovey
Updated the pixbuf calls to gtk3.
225
        if email:
226
            # Convert downloaded image from provider to Gtk.Image
227
            loader = GdkPixbuf.PixbufLoader()
228
            loader.write(response.read())
229
            loader.close()
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
230
734.1.25 by Curtis Hovey
Updated the pixbuf calls to gtk3.
231
            for role in ["committer", "author"]:
232
                self._role_box_for(role).and_avatar_email(email).update_avatar_image_from_pixbuf_loader(loader)
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
233
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
234
    def _role_box_for(self, role):
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
235
        """ Return the Gtk.HBox for the given role """
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
236
        if role == "committer":
237
            return self.__committer_box
238
        else:
239
            return self.__authors_box