/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.4 by Curtis Hovey
Updated commit to gtk3.
17
from gi.repository import GObject
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
18
from gi.repository import Gtk
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.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
34
        GObject.GObject.__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
42
                self.name == other.name and
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
53
            if getattr(gtk, "Spinner", False):
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
54
                spinner = Gtk.Spinner()
729 by Jelmer Vernooij
Support use without gtk.Spinner, which is only available in pygtk >= 2.22.
55
                spinner.start()
56
                self.pack_start(spinner, False)
57
                spinner.set_tooltip_text(tooltip)
58
                spinner.set_size_request(20, 20)
59
                spinner.show()
60
            else:
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
61
                spinner = Gtk.Label(label=tooltip)
62
                self.pack_start(spinner, True, True, 0)
729 by Jelmer Vernooij
Support use without gtk.Spinner, which is only available in pygtk >= 2.22.
63
                self.set_tooltip_text(self.apparent_username)
64
                spinner.show()
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
65
        else:
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
66
            no_email = Gtk.Label(label=_i18n("No email"))
67
            self.pack_start(no_email, True, True, 0)
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
68
            self.set_tooltip_text(self.apparent_username)
69
            no_email.show()
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
70
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
71
    def show_image(self):
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
72
        """Replace the current content of the Avatar with the Gtk.Image """
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
73
        if self.email and self.image:
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
74
            self.remove(self.get_children()[0])
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
75
            self.pack_start(self.image, True, True, 0)
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
76
            self.image.set_tooltip_text(self.apparent_username)
77
            self.image.show()
78
79
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
80
class AvatarBox(Gtk.HBox):
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
81
    """HBox showing an avatar."""
82
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
83
    def __init__(self, homogeneous=False, spacing=0):
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
84
        GObject.GObject.__init__(self, homogeneous, spacing)
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
85
        self.__avatars = {}
86
        self.avatar = None
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 reset_view(self):
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
90
        """Remove current avatars from the gtk box."""
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
91
        for child in self.get_children():
92
            self.remove(child)
93
        self.__displaying = None
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
94
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
95
    def have_avatar(self, avatar):
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
96
        """Return True if this box has the specified avatar.
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
97
        """
98
        return avatar.email in self.__avatars
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
99
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
100
    def showing(self, avatar):
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
101
        """Return True if the displaying avatar matches the specified one.
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
102
        """
103
        return self.__displaying and self.__displaying == avatar
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
104
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
105
    def append_avatars_with(self, avatar):
106
        """
107
        Append avatars collection with the given one if not already registed
108
        otherwise render it back.
109
        When an avatar is added this method True, otherwise, if the avatar
110
        was in the collection, return False.
111
        """
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
112
        if avatar.email and not avatar.email in self.__avatars:
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
113
            self.__avatars[avatar.email] = avatar
114
            self._new_cell_for_avatar(avatar)
115
            return True
116
        else:
117
            self.and_avatar_email(avatar.email).come_back_to_gui()
118
        return False
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
119
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
120
    def and_avatar_email(self, email):
121
        """
122
        Select the avatar from avatars collection
123
        in order to apply future actions
124
        """
125
        self.avatar = None
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
126
        if email and email in self.__avatars:
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
127
            self.avatar = self.__avatars[email]
128
        else:
129
            self.avatar = None
130
        return self
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
131
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
132
    def update_avatar_image_from_pixbuf_loader(self, loader):
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
133
        """Replace the Gtk.Spinner with the given loader."""
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
134
        if self.avatar:
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
135
            self.avatar.image = Gtk.Image()
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
136
            self.avatar.image.set_from_pixbuf(loader.get_pixbuf())
137
            self.avatar.show_image()
138
            self.__displaying = self.avatar
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
139
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
140
    def come_back_to_gui(self):
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
141
        """Render back avatar in the GUI."""
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
142
        if self.avatar:
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
143
            self.pack_start(self.avatar, True, True, 0)
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
144
            self.__displaying = self.avatar
145
        else:
146
            self._show_no_email()
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
147
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
148
    def _new_cell_for_avatar(self, avatar):
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
149
        """Create a new cell in this box with a Gtk.Spinner."""
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
150
        avatar.show_spinner()
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
151
        self.pack_start(avatar, True, True, 0)
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
152
        avatar.show()
153
        self.__displaying = avatar
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
154
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
155
    def _show_no_email(self):
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
156
        """Show a Gtk.Label with test 'No email'."""
157
        no_email = Gtk.Label(label=_i18n("No email"))
158
        self.pack_start(no_email, True, True, 0)
719.2.4 by zedtux
Moved Avatar and AvatarBox classes into avatarsbox file
159
        no_email.show()
160
161
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
162
class AvatarsBox(Gtk.HBox):
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
163
    """GTK container for author and committer avatars."""
164
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
165
    def __init__(self):
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
166
        GObject.GObject.__init__(self, False, 10)
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
167
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
168
        self.__committer_box = None
169
        self.__authors_box = None
170
        self._init_gui()
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
171
172
        # If more later you want to implement more avatar providers:
173
        # * Create a new class named AvatarProvider + provider_name that
174
        #   inherit from the AvatarProvider class.
175
        # * Implement a method that return url to use in the request.
176
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
177
        # For example, with Gravatar, the method return the complete url
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
178
        # with MD5 hash of the email address and put the value in a
179
        # gravatar_id field.
180
        # 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)
181
        provider = AvatarProviderGravatar()
182
        self.__worker = AvatarDownloaderWorker(
183
            provider.gravatar_id_for_email
184
        )
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
185
        # This callback method should be fired by all workers when a request
186
        # is done.
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
187
        self.__worker.set_callback_method(self._update_avatar_from_response)
188
        self.__worker.start()
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
189
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
190
    def add(self, username, role):
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
191
        """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)
192
        """
193
        avatar = Avatar(username)
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
194
        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)
195
            if self._role_box_for(role).append_avatars_with(avatar):
196
                self.__worker.queue(avatar.email)
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
197
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
198
    def merge(self, usernames, role):
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
199
        """Add avatars from a list"""
719.2.2 by zedtux
Patched code following Jelmer's recommandations
200
        for username in usernames:
201
            self.add(username, role)
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
202
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
203
    def reset(self):
204
        """
205
        Request a reset view for all boxes in order to show only avatars
206
        of the selected line in the revision view screen.
207
        """
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
208
        for role in ("committer", "author"):
209
            self._role_box_for(role).reset_view()
210
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
211
    def _init_gui(self):
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
212
        """Create boxes where avatars will be displayed."""
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
213
        # 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)
214
        # Committer
215
        self.__committer_box = AvatarBox()
216
        self.__committer_box.set_size_request(80, 80)
217
        self.pack_end(self.__committer_box, False)
218
        self.__committer_box.show()
219
        # Authors
220
        self.__authors_box = AvatarBox()
221
        self.pack_end(self.__authors_box, False)
222
        self.__authors_box.set_spacing(10)
223
        self.__authors_box.show()
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
224
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
225
    def _update_avatar_from_response(self, response, email):
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
226
        """Callback method fired by avatar worker when finished.
227
228
        :param response: a urllib2.urlopen() return value.
229
        :param email: used to identify item from self.__avatars.
230
        """
231
        if email:
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
232
            # Convert downloaded image from provider to Gtk.Image
233
            loader = GdkPixbuf.PixbufLoader()
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
234
            loader.write(response.read())
235
            loader.close()
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
236
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
237
            for role in ["committer", "author"]:
238
                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.
239
719.2.1 by zedtux
Added committers and authors avatars from Gravatar (urllib2 version)
240
    def _role_box_for(self, role):
734.1.1 by Curtis Hovey
Mechanical changes made by pygi.convert.sh.
241
        """ Return the Gtk.HBox for the given role """
728 by Jelmer Vernooij
Cleanups, fix compatibility with older versions of pygtk.
242
        if role == "committer":
243
            return self.__committer_box
244
        else:
245
            return self.__authors_box