root/trunk/src/vcard.py

Revision 10630, 18.8 kB (checked in by jim++, 3 weeks ago)

Removed some unused imports

  • Property svn:eol-style set to LF
Line 
1# -*- coding:utf-8 -*-
2## src/vcard.py
3##
4## Copyright (C) 2003-2008 Yann Leboulanger <asterix AT lagaule.org>
5## Copyright (C) 2005 Vincent Hanquez <tab AT snarc.org>
6## Copyright (C) 2005-2006 Nikos Kouremenos <kourem AT gmail.com>
7## Copyright (C) 2006 Junglecow J <junglecow AT gmail.com>
8##                    Dimitur Kirov <dkirov AT gmail.com>
9##                    Travis Shirk <travis AT pobox.com>
10##                    Stefan Bethge <stefan AT lanpartei.de>
11## Copyright (C) 2006-2008 Jean-Marie Traissard <jim AT lapin.org>
12## Copyright (C) 2007 Lukas Petrovicky <lukas AT petrovicky.net>
13## Copyright (C) 2008 Brendan Taylor <whateley AT gmail.com>
14##                    Jonathan Schleifer <js-gajim AT webkeks.org>
15##                    Stephan Erb <steve-e AT h3c.de>
16##
17## This file is part of Gajim.
18##
19## Gajim is free software; you can redistribute it and/or modify
20## it under the terms of the GNU General Public License as published
21## by the Free Software Foundation; version 3 only.
22##
23## Gajim is distributed in the hope that it will be useful,
24## but WITHOUT ANY WARRANTY; without even the implied warranty of
25## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26## GNU General Public License for more details.
27##
28## You should have received a copy of the GNU General Public License
29## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
30##
31
32# THIS FILE IS FOR **OTHERS'** PROFILE (when we VIEW their INFO)
33
34import gtk
35import gobject
36import base64
37import time
38import locale
39import os
40
41import gtkgui_helpers
42
43from common import helpers
44from common import gajim
45from common.i18n import Q_
46
47def get_avatar_pixbuf_encoded_mime(photo):
48        '''return the pixbuf of the image
49        photo is a dictionary containing PHOTO information'''
50        if not isinstance(photo, dict):
51                return None, None, None
52        img_decoded = None
53        avatar_encoded = None
54        avatar_mime_type = None
55        if 'BINVAL' in photo:
56                img_encoded = photo['BINVAL']
57                avatar_encoded = img_encoded
58                try:
59                        img_decoded = base64.decodestring(img_encoded)
60                except Exception:
61                        pass
62        if img_decoded:
63                if 'TYPE' in photo:
64                        avatar_mime_type = photo['TYPE']
65                        pixbuf = gtkgui_helpers.get_pixbuf_from_data(img_decoded)
66                else:
67                        pixbuf, avatar_mime_type = gtkgui_helpers.get_pixbuf_from_data(
68                                                        img_decoded, want_type=True)
69        else:
70                pixbuf = None
71        return pixbuf, avatar_encoded, avatar_mime_type
72
73class VcardWindow:
74        '''Class for contact's information window'''
75
76        def __init__(self, contact, account, gc_contact = None):
77                # the contact variable is the jid if vcard is true
78                self.xml = gtkgui_helpers.get_glade('vcard_information_window.glade')
79                self.window = self.xml.get_widget('vcard_information_window')
80                self.progressbar = self.xml.get_widget('progressbar')
81
82                self.contact = contact
83                self.account = account
84                self.gc_contact = gc_contact
85
86                # Get real jid
87                if gc_contact:
88                        # Don't use real jid if room is (semi-)anonymous
89                        gc_control = gajim.interface.msg_win_mgr.get_gc_control(
90                        gc_contact.room_jid, account)
91                        if gc_contact.jid and not gc_control.is_anonymous:
92                                self.real_jid = gc_contact.jid
93                                if gc_contact.resource:
94                                        self.real_jid += '/' + gc_contact.resource
95                        else:
96                                self.real_jid = gc_contact.get_full_jid()
97                else:
98                        self.real_jid = contact.get_full_jid()
99
100                puny_jid = helpers.sanitize_filename(contact.jid)
101                local_avatar_basepath = os.path.join(gajim.AVATAR_PATH, puny_jid) + \
102                        '_local'
103                for extension in ('.png', '.jpeg'):
104                        local_avatar_path = local_avatar_basepath + extension
105                        if os.path.isfile(local_avatar_path):
106                                image = self.xml.get_widget('custom_avatar_image')
107                                image.set_from_file(local_avatar_path)
108                                image.show()
109                                self.xml.get_widget('custom_avatar_label').show()
110                                break
111                self.avatar_mime_type = None
112                self.avatar_encoded = None
113                self.vcard_arrived = False
114                self.os_info_arrived = False
115                self.update_progressbar_timeout_id = gobject.timeout_add(100,
116                        self.update_progressbar)
117
118                self.fill_jabber_page()
119                annotations = gajim.connections[self.account].annotations
120                if self.contact.jid in annotations:
121                        buffer = self.xml.get_widget('textview_annotation').get_buffer()
122                        buffer.set_text(annotations[self.contact.jid])
123
124                self.xml.signal_autoconnect(self)
125                self.window.show_all()
126                self.xml.get_widget('close_button').grab_focus()
127
128        def update_progressbar(self):
129                self.progressbar.pulse()
130                return True # loop forever
131
132        def on_vcard_information_window_destroy(self, widget):
133                if self.update_progressbar_timeout_id is not None:
134                        gobject.source_remove(self.update_progressbar_timeout_id)
135                del gajim.interface.instances[self.account]['infos'][self.contact.jid]
136                buffer = self.xml.get_widget('textview_annotation').get_buffer()
137                annotation = buffer.get_text(buffer.get_start_iter(),
138                        buffer.get_end_iter())
139                connection = gajim.connections[self.account]
140                if annotation != connection.annotations.get(self.contact.jid, ''):
141                        connection.annotations[self.contact.jid] = annotation
142                        connection.store_annotations()
143
144        def on_vcard_information_window_key_press_event(self, widget, event):
145                if event.keyval == gtk.keysyms.Escape:
146                        self.window.destroy()
147
148        def on_PHOTO_eventbox_button_press_event(self, widget, event):
149                '''If right-clicked, show popup'''
150                if event.button == 3: # right click
151                        menu = gtk.Menu()
152                        menuitem = gtk.ImageMenuItem(gtk.STOCK_SAVE_AS)
153                        menuitem.connect('activate',
154                                gtkgui_helpers.on_avatar_save_as_menuitem_activate,
155                                self.contact.jid, self.account, self.contact.get_shown_name() +
156                                '.jpeg')
157                        menu.append(menuitem)
158                        menu.connect('selection-done', lambda w:w.destroy())   
159                        # show the menu
160                        menu.show_all()
161                        menu.popup(None, None, None, event.button, event.time)
162
163        def set_value(self, entry_name, value):
164                try:
165                        if value and entry_name == 'URL_label':
166                                if gtk.pygtk_version >= (2, 10, 0) and gtk.gtk_version >= (2, 10, 0):
167                                        widget = gtk.LinkButton(value, value)
168                                        widget.set_alignment(0, 0)
169                                else:
170                                        widget = gtk.Label(value)
171                                        widget.set_alignment(0, 0)
172                                        widget.set_selectable(True)
173                                widget.show()
174                                table = self.xml.get_widget('personal_info_table')
175                                table.attach(widget, 1, 4, 3, 4, yoptions = 0)
176                        else:
177                                self.xml.get_widget(entry_name).set_text(value)
178                except AttributeError:
179                        pass
180
181        def set_values(self, vcard):
182                for i in vcard.keys():
183                        if i == 'PHOTO' and self.xml.get_widget('information_notebook').\
184                        get_n_pages() > 4:
185                                pixbuf, self.avatar_encoded, self.avatar_mime_type = \
186                                        get_avatar_pixbuf_encoded_mime(vcard[i])
187                                image = self.xml.get_widget('PHOTO_image')
188                                image.show()
189                                self.xml.get_widget('user_avatar_label').show()
190                                if not pixbuf:
191                                        image.set_from_icon_name('stock_person',
192                                                gtk.ICON_SIZE_DIALOG)
193                                        continue
194                                pixbuf = gtkgui_helpers.get_scaled_pixbuf(pixbuf, 'vcard')
195                                image.set_from_pixbuf(pixbuf)
196                                continue
197                        if i in ('ADR', 'TEL', 'EMAIL'):
198                                for entry in vcard[i]:
199                                        add_on = '_HOME'
200                                        if 'WORK' in entry:
201                                                add_on = '_WORK'
202                                        for j in entry.keys():
203                                                self.set_value(i + add_on + '_' + j + '_label', entry[j])
204                        if isinstance(vcard[i], dict):
205                                for j in vcard[i].keys():
206                                        self.set_value(i + '_' + j + '_label', vcard[i][j])
207                        else:
208                                if i == 'DESC':
209                                        self.xml.get_widget('DESC_textview').get_buffer().set_text(
210                                                vcard[i], 0)
211                                elif i != 'jid': # Do not override jid_label
212                                        self.set_value(i + '_label', vcard[i])
213                self.vcard_arrived = True
214                self.test_remove_progressbar()
215
216        def test_remove_progressbar(self):
217                if self.update_progressbar_timeout_id is not None and \
218                self.vcard_arrived and self.os_info_arrived:
219                        gobject.source_remove(self.update_progressbar_timeout_id)
220                        self.progressbar.hide()
221                        self.update_progressbar_timeout_id = None
222
223        def set_last_status_time(self):
224                self.fill_status_label()
225
226        def set_os_info(self, resource, client_info, os_info):
227                if self.xml.get_widget('information_notebook').get_n_pages() < 5:
228                        return
229                i = 0
230                client = ''
231                os = ''
232                while i in self.os_info:
233                        if not self.os_info[i]['resource'] or \
234                                        self.os_info[i]['resource'] == resource:
235                                self.os_info[i]['client'] = client_info
236                                self.os_info[i]['os'] = os_info
237                        if i > 0:
238                                client += '\n'
239                                os += '\n'
240                        client += self.os_info[i]['client']
241                        os += self.os_info[i]['os']
242                        i += 1
243
244                if client == '':
245                        client = Q_('?Client:Unknown')
246                if os == '':
247                        os = Q_('?OS:Unknown')
248                self.xml.get_widget('client_name_version_label').set_text(client)
249                self.xml.get_widget('os_label').set_text(os)
250                self.os_info_arrived = True
251                self.test_remove_progressbar()
252
253        def fill_status_label(self):
254                if self.xml.get_widget('information_notebook').get_n_pages() < 5:
255                        return
256                contact_list = gajim.contacts.get_contacts(self.account, self.contact.jid)
257                connected_contact_list = []
258                for c in contact_list:
259                        if c.show not in ('offline', 'error'):
260                                connected_contact_list.append(c)
261                if not connected_contact_list:
262                        # no connected contact, get the offline one
263                        connected_contact_list = contact_list
264                # stats holds show and status message
265                stats = ''
266                if connected_contact_list:
267                        # Start with self.contact, as with resources
268                        stats = helpers.get_uf_show(self.contact.show)
269                        if self.contact.status:
270                                stats += ': ' + self.contact.status
271                        if self.contact.last_status_time:
272                                stats += '\n' + _('since %s') % time.strftime('%c',
273                                        self.contact.last_status_time).decode(
274                                        locale.getpreferredencoding())
275                        for c in connected_contact_list:
276                                if c.resource != self.contact.resource:
277                                        stats += '\n'
278                                        stats += helpers.get_uf_show(c.show)
279                                        if c.status:
280                                                stats += ': ' + c.status
281                                        if c.last_status_time:
282                                                stats += '\n' + _('since %s') % time.strftime('%c',
283                                                        c.last_status_time).decode(locale.getpreferredencoding())
284                else: # Maybe gc_vcard ?
285                        stats = helpers.get_uf_show(self.contact.show)
286                        if self.contact.status:
287                                stats += ': ' + self.contact.status
288                status_label = self.xml.get_widget('status_label')
289                status_label.set_max_width_chars(15)
290                status_label.set_text(stats)
291
292                tip = gtk.Tooltips()
293                status_label_eventbox = self.xml.get_widget('status_label_eventbox')
294                tip.set_tip(status_label_eventbox, stats)
295
296        def fill_jabber_page(self):
297                tooltips = gtk.Tooltips()
298                self.xml.get_widget('nickname_label').set_markup(
299                        '<b><span size="x-large">' +
300                        self.contact.get_shown_name() +
301                        '</span></b>')
302                self.xml.get_widget('jid_label').set_text(self.contact.jid)
303               
304                subscription_label = self.xml.get_widget('subscription_label')
305                ask_label = self.xml.get_widget('ask_label')
306                if self.gc_contact:
307                        self.xml.get_widget('subscription_title_label').set_markup(_("<b>Role:</b>"))
308                        uf_role = helpers.get_uf_role(self.gc_contact.role)
309                        subscription_label.set_text(uf_role)
310
311                        self.xml.get_widget('ask_title_label').set_markup(_("<b>Affiliation:</b>"))
312                        uf_affiliation = helpers.get_uf_affiliation(self.gc_contact.affiliation)
313                        ask_label.set_text(uf_affiliation)
314                else:
315                        uf_sub = helpers.get_uf_sub(self.contact.sub)
316                        subscription_label.set_text(uf_sub)
317                        eb = self.xml.get_widget('subscription_label_eventbox')
318                        if self.contact.sub == 'from':
319                                tt_text = _("This contact is interested in your presence information, but you are not interested in his/her presence")
320                        elif self.contact.sub == 'to':
321                                tt_text = _("You are interested in the contact's presence information, but he/she is not interested in yours")
322                        elif self.contact.sub == 'both':
323                                tt_text = _("You and the contact are interested in each other's presence information")
324                        else: # None
325                                tt_text = _("You are not interested in the contact's presence, and neither he/she is interested in yours")
326                        tooltips.set_tip(eb, tt_text)
327
328                        uf_ask = helpers.get_uf_ask(self.contact.ask)
329                        ask_label.set_text(uf_ask)
330                        eb = self.xml.get_widget('ask_label_eventbox')
331                        if self.contact.ask == 'subscribe':
332                                tt_text = _("You are waiting contact's answer about your subscription request")
333                        else:
334                                tt_text = _("There is no pending subscription request.")
335                        tooltips.set_tip(eb, tt_text)
336
337                resources = '%s (%s)' % (self.contact.resource, unicode(
338                        self.contact.priority))
339                uf_resources = self.contact.resource + _(' resource with priority ')\
340                        + unicode(self.contact.priority)
341                if not self.contact.status:
342                        self.contact.status = ''
343
344                # Request list time status only if contact is offline
345                if self.contact.show == 'offline':
346                        if self.gc_contact:
347                                j, r = gajim.get_room_and_nick_from_fjid(self.real_jid)
348                                gajim.connections[self.account].request_last_status_time(j, r,
349                                        self.contact.jid)
350                        else:
351                                gajim.connections[self.account].request_last_status_time(
352                                        self.contact.jid, self.contact.resource)
353
354                # do not wait for os_info if contact is not connected or has error
355                # additional check for observer is needed, as show is offline for him
356                if self.contact.show in ('offline', 'error')\
357                and not self.contact.is_observer():
358                        self.os_info_arrived = True
359                else: # Request os info if contact is connected
360                        if self.gc_contact:
361                                j, r = gajim.get_room_and_nick_from_fjid(self.real_jid)
362                                gobject.idle_add(gajim.connections[self.account].request_os_info,
363                                        j, r, self.contact.jid)
364                        else:
365                                gobject.idle_add(gajim.connections[self.account].request_os_info,
366                                        self.contact.jid, self.contact.resource)
367                self.os_info = {0: {'resource': self.contact.resource, 'client': '',
368                        'os': ''}}
369                i = 1
370                contact_list = gajim.contacts.get_contacts(self.account, self.contact.jid)
371                if contact_list:
372                        for c in contact_list:
373                                if c.resource != self.contact.resource:
374                                        resources += '\n%s (%s)' % (c.resource,
375                                                unicode(c.priority))
376                                        uf_resources += '\n' + c.resource + \
377                                                _(' resource with priority ') + unicode(c.priority)
378                                        if c.show not in ('offline', 'error'):
379                                                gobject.idle_add(
380                                                        gajim.connections[self.account].request_os_info, c.jid,
381                                                        c.resource)
382                                        gajim.connections[self.account].request_last_status_time(c.jid,
383                                                c.resource)
384                                        self.os_info[i] = {'resource': c.resource, 'client': '',
385                                                'os': ''}
386                                        i += 1
387                self.xml.get_widget('resource_prio_label').set_text(resources)
388                resource_prio_label_eventbox = self.xml.get_widget(
389                        'resource_prio_label_eventbox')
390                tooltips.set_tip(resource_prio_label_eventbox, uf_resources)
391
392                self.fill_status_label()
393
394                if self.gc_contact:
395                        # If we know the real jid, remove the resource from vcard request
396                        if self.gc_contact.jid:
397                                jid = self.gc_contact.jid
398                        else:
399                                jid = self.real_jid
400                        gajim.connections[self.account].request_vcard(jid,
401                                self.gc_contact.get_full_jid())
402                else:
403                        gajim.connections[self.account].request_vcard(self.contact.jid)
404
405        def on_close_button_clicked(self, widget):
406                self.window.destroy()
407
408
409class ZeroconfVcardWindow:
410        def __init__(self, contact, account, is_fake = False):
411                # the contact variable is the jid if vcard is true
412                self.xml = gtkgui_helpers.get_glade('zeroconf_information_window.glade')
413                self.window = self.xml.get_widget('zeroconf_information_window')
414
415                self.contact = contact
416                self.account = account
417                self.is_fake = is_fake
418
419        #       self.avatar_mime_type = None
420        #       self.avatar_encoded = None
421
422                self.fill_contact_page()
423                self.fill_personal_page()
424
425                self.xml.signal_autoconnect(self)
426                self.window.show_all()
427
428        def on_zeroconf_information_window_destroy(self, widget):
429                del gajim.interface.instances[self.account]['infos'][self.contact.jid]
430
431        def on_zeroconf_information_window_key_press_event(self, widget, event):
432                if event.keyval == gtk.keysyms.Escape:
433                        self.window.destroy()
434
435        def on_PHOTO_eventbox_button_press_event(self, widget, event):
436                '''If right-clicked, show popup'''
437                if event.button == 3: # right click
438                        menu = gtk.Menu()
439                        menuitem = gtk.ImageMenuItem(gtk.STOCK_SAVE_AS)
440                        menuitem.connect('activate',
441                                gtkgui_helpers.on_avatar_save_as_menuitem_activate,
442                                self.contact.jid, self.account, self.contact.get_shown_name() +
443                                '.jpeg')
444                        menu.append(menuitem)
445                        menu.connect('selection-done', lambda w:w.destroy())   
446                        # show the menu
447                        menu.show_all()
448                        menu.popup(None, None, None, event.button, event.time)
449
450        def set_value(self, entry_name, value):
451                try:
452                        if value and entry_name == 'URL_label':
453                                if gtk.pygtk_version >= (2, 10, 0) and gtk.gtk_version >= (2, 10, 0):
454                                        widget = gtk.LinkButton(value, value)
455                                        widget.set_alignment(0, 0)
456                                else:
457                                        widget = gtk.Label(value)
458                                        widget.set_selectable(True)
459                                        widget.set_alignment(0, 0)
460                                table = self.xml.get_widget('personal_info_table')
461                                table.attach(widget, 1, 4, 3, 4, yoptions = 0)
462                        else:
463                                self.xml.get_widget(entry_name).set_text(value)
464                except AttributeError:
465                        pass
466
467        def fill_status_label(self):
468                if self.xml.get_widget('information_notebook').get_n_pages() < 2:
469                        return
470                contact_list = gajim.contacts.get_contacts(self.account, self.contact.jid)
471                # stats holds show and status message
472                stats = ''
473                one = True # Are we adding the first line ?
474                if contact_list:
475                        for c in contact_list:
476                                if not one:
477                                        stats += '\n'
478                                stats += helpers.get_uf_show(c.show)
479                                if c.status:
480                                        stats += ': ' + c.status
481                                if c.last_status_time:
482                                        stats += '\n' + _('since %s') % time.strftime('%c',
483                                                c.last_status_time).decode(locale.getpreferredencoding())
484                                one = False
485                else: # Maybe gc_vcard ?
486                        stats = helpers.get_uf_show(self.contact.show)
487                        if self.contact.status:
488                                stats += ': ' + self.contact.status
489                status_label = self.xml.get_widget('status_label')
490                status_label.set_max_width_chars(15)
491                status_label.set_text(stats)
492
493                tip = gtk.Tooltips()
494                status_label_eventbox = self.xml.get_widget('status_label_eventbox')
495                tip.set_tip(status_label_eventbox, stats)
496       
497        def fill_contact_page(self):
498                tooltips = gtk.Tooltips()
499                self.xml.get_widget('nickname_label').set_markup(
500                        '<b><span size="x-large">' +
501                        self.contact.get_shown_name() +
502                        '</span></b>')
503                self.xml.get_widget('local_jid_label').set_text(self.contact.jid)
504
505                resources = '%s (%s)' % (self.contact.resource, unicode(
506                        self.contact.priority))
507                uf_resources = self.contact.resource + _(' resource with priority ')\
508                        + unicode(self.contact.priority)
509                if not self.contact.status:
510                        self.contact.status = ''
511
512                # Request list time status
513        #       gajim.connections[self.account].request_last_status_time(self.contact.jid,
514        #               self.contact.resource)
515
516                self.xml.get_widget('resource_prio_label').set_text(resources)
517                resource_prio_label_eventbox = self.xml.get_widget(
518                        'resource_prio_label_eventbox')
519                tooltips.set_tip(resource_prio_label_eventbox, uf_resources)
520
521                self.fill_status_label()
522
523        #       gajim.connections[self.account].request_vcard(self.contact.jid, self.is_fake)
524       
525        def fill_personal_page(self):
526                contact = gajim.connections[gajim.ZEROCONF_ACC_NAME].roster.getItem(self.contact.jid)
527                for key in ('1st', 'last', 'jid', 'email'):
528                        if key not in contact['txt_dict']:
529                                contact['txt_dict'][key] = ''
530                self.xml.get_widget('first_name_label').set_text(contact['txt_dict']['1st'])
531                self.xml.get_widget('last_name_label').set_text(contact['txt_dict']['last'])
532                self.xml.get_widget('jabber_id_label').set_text(contact['txt_dict']['jid'])
533                self.xml.get_widget('email_label').set_text(contact['txt_dict']['email'])
534
535        def on_close_button_clicked(self, widget):
536                self.window.destroy()
537
538# vim: se ts=3:
Note: See TracBrowser for help on using the browser.