root/trunk/src/profile_window.py

Revision 10549, 11.6 kB (checked in by asterix, 6 weeks ago)

revert thorstenp patches for now. They introduce bugs.

Line 
1# -*- coding:utf-8 -*-
2## src/profile_window.py
3##
4## Copyright (C) 2003-2008 Yann Leboulanger <asterix AT lagaule.org>
5## Copyright (C) 2005-2006 Nikos Kouremenos <kourem AT gmail.com>
6## Copyright (C) 2006-2008 Jean-Marie Traissard <jim AT lapin.org>
7##
8## This file is part of Gajim.
9##
10## Gajim is free software; you can redistribute it and/or modify
11## it under the terms of the GNU General Public License as published
12## by the Free Software Foundation; version 3 only.
13##
14## Gajim is distributed in the hope that it will be useful,
15## but WITHOUT ANY WARRANTY; without even the implied warranty of
16## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17## GNU General Public License for more details.
18##
19## You should have received a copy of the GNU General Public License
20## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
21##
22
23# THIS FILE IS FOR **OUR** PROFILE (when we edit our INFO)
24
25import gtk
26import gobject
27import base64
28import mimetypes
29import os
30
31import gtkgui_helpers
32import dialogs
33import vcard
34
35from common import gajim
36from common.i18n import Q_
37
38
39class ProfileWindow:
40        '''Class for our information window'''
41
42        def __init__(self, account):
43                self.xml = gtkgui_helpers.get_glade('profile_window.glade')
44                self.window = self.xml.get_widget('profile_window')
45                self.progressbar = self.xml.get_widget('progressbar')
46                self.statusbar = self.xml.get_widget('statusbar')
47                self.context_id = self.statusbar.get_context_id('profile')
48
49                self.account = account
50                self.jid = gajim.get_jid_from_account(account)
51
52                self.dialog = None
53                self.avatar_mime_type = None
54                self.avatar_encoded = None
55                self.message_id = self.statusbar.push(self.context_id,
56                        _('Retrieving profile...'))
57                self.update_progressbar_timeout_id = gobject.timeout_add(100,
58                        self.update_progressbar)
59                self.remove_statusbar_timeout_id = None
60
61                # Create Image for avatar button
62                image = gtk.Image()
63                self.xml.get_widget('PHOTO_button').set_image(image)
64                self.xml.signal_autoconnect(self)
65                self.window.show_all()
66
67        def update_progressbar(self):
68                self.progressbar.pulse()
69                return True # loop forever
70
71        def remove_statusbar(self, message_id):
72                self.statusbar.remove(self.context_id, message_id)
73                self.remove_statusbar_timeout_id = None
74
75        def on_profile_window_destroy(self, widget):
76                if self.update_progressbar_timeout_id is not None:
77                        gobject.source_remove(self.update_progressbar_timeout_id)
78                if self.remove_statusbar_timeout_id is not None:
79                        gobject.source_remove(self.remove_statusbar_timeout_id)
80                del gajim.interface.instances[self.account]['profile']
81                if self.dialog: # Image chooser dialog
82                        self.dialog.destroy()
83
84        def on_profile_window_key_press_event(self, widget, event):
85                if event.keyval == gtk.keysyms.Escape:
86                        self.window.destroy()
87
88        def on_clear_button_clicked(self, widget):
89                # empty the image
90                button = self.xml.get_widget('PHOTO_button')
91                image = button.get_image()
92                image.set_from_pixbuf(None)
93                button.hide()
94                text_button = self.xml.get_widget('NOPHOTO_button')
95                text_button.show()
96                self.avatar_encoded = None
97                self.avatar_mime_type = None
98
99        def on_set_avatar_button_clicked(self, widget):
100                def on_ok(widget, path_to_file):
101                        must_delete = False
102                        filesize = os.path.getsize(path_to_file) # in bytes
103                        invalid_file = False
104                        msg = ''
105                        if os.path.isfile(path_to_file):
106                                stat = os.stat(path_to_file)
107                                if stat[6] == 0:
108                                        invalid_file = True
109                                        msg = _('File is empty')
110                        else:
111                                invalid_file = True
112                                msg = _('File does not exist')
113                        if not invalid_file and filesize > 16384: # 16 kb
114                                try:
115                                        pixbuf = gtk.gdk.pixbuf_new_from_file(path_to_file)
116                                        # get the image at 'notification size'
117                                        # and hope that user did not specify in ACE crazy size
118                                        scaled_pixbuf = gtkgui_helpers.get_scaled_pixbuf(pixbuf,
119                                                'tooltip')
120                                except gobject.GError, msg: # unknown format
121                                        # msg should be string, not object instance
122                                        msg = str(msg)
123                                        invalid_file = True
124                        if invalid_file:
125                                if True: # keep identation
126                                        dialogs.ErrorDialog(_('Could not load image'), msg)
127                                        return
128                        if filesize > 16384:
129                                        if scaled_pixbuf:
130                                                path_to_file = os.path.join(gajim.TMP,
131                                                        'avatar_scaled.png')
132                                                scaled_pixbuf.save(path_to_file, 'png')
133                                                must_delete = True
134                       
135                        fd = open(path_to_file, 'rb')
136                        data = fd.read()
137                        pixbuf = gtkgui_helpers.get_pixbuf_from_data(data)
138                        try:                   
139                                # rescale it
140                                pixbuf = gtkgui_helpers.get_scaled_pixbuf(pixbuf, 'vcard')
141                        except AttributeError: # unknown format
142                                dialogs.ErrorDialog(_('Could not load image'))
143                                return
144                        self.dialog.destroy()
145                        self.dialog = None
146                        button = self.xml.get_widget('PHOTO_button')
147                        image = button.get_image()
148                        image.set_from_pixbuf(pixbuf)
149                        button.show()
150                        text_button = self.xml.get_widget('NOPHOTO_button')
151                        text_button.hide()
152                        self.avatar_encoded = base64.encodestring(data)
153                        # returns None if unknown type
154                        self.avatar_mime_type = mimetypes.guess_type(path_to_file)[0]
155                        if must_delete: 
156                                try: 
157                                        os.remove(path_to_file) 
158                                except OSError: 
159                                        gajim.log.debug('Cannot remove %s' % path_to_file)
160
161                def on_clear(widget):
162                        self.dialog.destroy()
163                        self.dialog = None
164                        self.on_clear_button_clicked(widget)
165
166                def on_cancel(widget):
167                        self.dialog.destroy()
168                        self.dialog = None
169
170                if self.dialog:
171                        self.dialog.present()
172                else:
173                        self.dialog = dialogs.AvatarChooserDialog(on_response_ok = on_ok,
174                                on_response_cancel = on_cancel, on_response_clear = on_clear)
175
176        def on_PHOTO_button_press_event(self, widget, event):
177                '''If right-clicked, show popup'''
178                if event.button == 3 and self.avatar_encoded: # right click
179                        menu = gtk.Menu()
180                       
181                        # Try to get pixbuf
182                        pixbuf = gtkgui_helpers.get_avatar_pixbuf_from_cache(self.jid,
183                                use_local = False)
184
185                        if pixbuf:
186                                nick = gajim.config.get_per('accounts', self.account, 'name')
187                                menuitem = gtk.ImageMenuItem(gtk.STOCK_SAVE_AS)
188                                menuitem.connect('activate',
189                                        gtkgui_helpers.on_avatar_save_as_menuitem_activate,
190                                        self.jid, None, nick + '.jpeg')
191                                menu.append(menuitem)
192                        # show clear
193                        menuitem = gtk.ImageMenuItem(gtk.STOCK_CLEAR)
194                        menuitem.connect('activate', self.on_clear_button_clicked)
195                        menu.append(menuitem)
196                        menu.connect('selection-done', lambda w:w.destroy())   
197                        # show the menu
198                        menu.show_all()
199                        menu.popup(None, None, None, event.button, event.time)
200                elif event.button == 1: # left click
201                        self.on_set_avatar_button_clicked(widget)
202
203        def set_value(self, entry_name, value):
204                try:
205                        self.xml.get_widget(entry_name).set_text(value)
206                except AttributeError:
207                        pass
208
209        def set_values(self, vcard_):
210                button = self.xml.get_widget('PHOTO_button')
211                image = button.get_image()
212                text_button = self.xml.get_widget('NOPHOTO_button')
213                if not 'PHOTO' in vcard_:
214                        # set default image
215                        image.set_from_pixbuf(None)
216                        button.hide()
217                        text_button.show()
218                for i in vcard_.keys():
219                        if i == 'PHOTO':
220                                pixbuf, self.avatar_encoded, self.avatar_mime_type = \
221                                        vcard.get_avatar_pixbuf_encoded_mime(vcard_[i])
222                                if not pixbuf:
223                                        image.set_from_pixbuf(None)
224                                        button.hide()
225                                        text_button.show()
226                                        continue
227                                pixbuf = gtkgui_helpers.get_scaled_pixbuf(pixbuf, 'vcard')
228                                image.set_from_pixbuf(pixbuf)
229                                button.show()
230                                text_button.hide()
231                                continue
232                        if i == 'ADR' or i == 'TEL' or i == 'EMAIL':
233                                for entry in vcard_[i]:
234                                        add_on = '_HOME'
235                                        if 'WORK' in entry:
236                                                add_on = '_WORK'
237                                        for j in entry.keys():
238                                                self.set_value(i + add_on + '_' + j + '_entry', entry[j])
239                        if isinstance(vcard_[i], dict):
240                                for j in vcard_[i].keys():
241                                        self.set_value(i + '_' + j + '_entry', vcard_[i][j])
242                        else:
243                                if i == 'DESC':
244                                        self.xml.get_widget('DESC_textview').get_buffer().set_text(
245                                                vcard_[i], 0)
246                                else:
247                                        self.set_value(i + '_entry', vcard_[i])
248                if self.update_progressbar_timeout_id is not None:
249                        if self.message_id:
250                                self.statusbar.remove(self.context_id, self.message_id)
251                        self.message_id = self.statusbar.push(self.context_id,
252                                _('Information received'))
253                        self.remove_statusbar_timeout_id = gobject.timeout_add_seconds(3,
254                                self.remove_statusbar, self.message_id)
255                        gobject.source_remove(self.update_progressbar_timeout_id)
256                        self.progressbar.hide()
257                        self.progressbar.set_fraction(0)
258                        self.update_progressbar_timeout_id = None
259
260        def add_to_vcard(self, vcard_, entry, txt):
261                '''Add an information to the vCard dictionary'''
262                entries = entry.split('_')
263                loc = vcard_
264                if len(entries) == 3: # We need to use lists
265                        if entries[0] not in loc:
266                                loc[entries[0]] = []
267                        found = False
268                        for e in loc[entries[0]]:
269                                if entries[1] in e:
270                                        found = True
271                                        break
272                        if found:
273                                e[entries[2]] = txt
274                        else:
275                                loc[entries[0]].append({entries[1]: '', entries[2]: txt})
276                        return vcard_
277                while len(entries) > 1:
278                        if entries[0] not in loc:
279                                loc[entries[0]] = {}
280                        loc = loc[entries[0]]
281                        del entries[0]
282                loc[entries[0]] = txt
283                return vcard_
284
285        def make_vcard(self):
286                '''make the vCard dictionary'''
287                entries = ['FN', 'NICKNAME', 'BDAY', 'EMAIL_HOME_USERID', 'URL',
288                        'TEL_HOME_NUMBER', 'N_FAMILY', 'N_GIVEN', 'N_MIDDLE', 'N_PREFIX',
289                        'N_SUFFIX', 'ADR_HOME_STREET', 'ADR_HOME_EXTADR', 'ADR_HOME_LOCALITY',
290                        'ADR_HOME_REGION', 'ADR_HOME_PCODE', 'ADR_HOME_CTRY', 'ORG_ORGNAME',
291                        'ORG_ORGUNIT', 'TITLE', 'ROLE', 'TEL_WORK_NUMBER', 'EMAIL_WORK_USERID',
292                        'ADR_WORK_STREET', 'ADR_WORK_EXTADR', 'ADR_WORK_LOCALITY',
293                        'ADR_WORK_REGION', 'ADR_WORK_PCODE', 'ADR_WORK_CTRY']
294                vcard_ = {}
295                for e in entries: 
296                        txt = self.xml.get_widget(e + '_entry').get_text().decode('utf-8')
297                        if txt != '':
298                                vcard_ = self.add_to_vcard(vcard_, e, txt)
299
300                # DESC textview
301                buff = self.xml.get_widget('DESC_textview').get_buffer()
302                start_iter = buff.get_start_iter()
303                end_iter = buff.get_end_iter()
304                txt = buff.get_text(start_iter, end_iter, 0)
305                if txt != '':
306                        vcard_['DESC'] = txt.decode('utf-8')
307
308                # Avatar
309                if self.avatar_encoded:
310                        vcard_['PHOTO'] = {'BINVAL': self.avatar_encoded}
311                        if self.avatar_mime_type:
312                                vcard_['PHOTO']['TYPE'] = self.avatar_mime_type
313                return vcard_
314
315        def on_ok_button_clicked(self, widget):
316                if self.update_progressbar_timeout_id:
317                        # Operation in progress
318                        return
319                if gajim.connections[self.account].connected < 2:
320                        dialogs.ErrorDialog(_('You are not connected to the server'),
321                                _('Without a connection you can not publish your contact '
322                                'information.'))
323                        return
324                vcard_ = self.make_vcard()
325                nick = ''
326                if 'NICKNAME' in vcard_:
327                        nick = vcard_['NICKNAME']
328                        from common import pep
329                        pep.user_send_nickname(self.account, nick)
330                if nick == '':
331                        nick = gajim.config.get_per('accounts', self.account, 'name')
332                gajim.nicks[self.account] = nick
333                gajim.connections[self.account].send_vcard(vcard_)
334                self.message_id = self.statusbar.push(self.context_id,
335                        _('Sending profile...'))
336                self.progressbar.show()
337                self.update_progressbar_timeout_id = gobject.timeout_add(100,
338                        self.update_progressbar)
339
340        def vcard_published(self):
341                if self.update_progressbar_timeout_id is not None:
342                        gobject.source_remove(self.update_progressbar_timeout_id)
343                        self.update_progressbar_timeout_id = None
344                self.window.destroy()
345
346        def vcard_not_published(self):
347                if self.message_id:
348                        self.statusbar.remove(self.context_id, self.message_id)
349                self.message_id = self.statusbar.push(self.context_id,
350                        _('Information NOT published'))
351                self.remove_statusbar_timeout_id = gobject.timeout_add_seconds(3,
352                        self.remove_statusbar, self.message_id)
353                if self.update_progressbar_timeout_id is not None:
354                        gobject.source_remove(self.update_progressbar_timeout_id)
355                        self.progressbar.set_fraction(0)
356                        self.update_progressbar_timeout_id = None
357                dialogs.InformationDialog(_('vCard publication failed'),
358                        _('There was an error while publishing your personal information, '
359                        'try again later.'))
360
361        def on_cancel_button_clicked(self, widget):
362                self.window.destroy()
363
364# vim: se ts=3:
Note: See TracBrowser for help on using the browser.