2 ## src/profile_window.py
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>
8 ## This file is part of Gajim.
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.
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.
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/>.
23 # THIS FILE IS FOR **OUR** PROFILE (when we edit our INFO)
35 from common
import gajim
39 '''Class for our information window'''
41 def __init__(self
, account
):
42 self
.xml
= gtkgui_helpers
.get_glade('profile_window.glade')
43 self
.window
= self
.xml
.get_widget('profile_window')
44 self
.progressbar
= self
.xml
.get_widget('progressbar')
45 self
.statusbar
= self
.xml
.get_widget('statusbar')
46 self
.context_id
= self
.statusbar
.get_context_id('profile')
48 self
.account
= account
49 self
.jid
= gajim
.get_jid_from_account(account
)
52 self
.avatar_mime_type
= None
53 self
.avatar_encoded
= None
54 self
.message_id
= self
.statusbar
.push(self
.context_id
,
55 _('Retrieving profile...'))
56 self
.update_progressbar_timeout_id
= gobject
.timeout_add(100,
57 self
.update_progressbar
)
58 self
.remove_statusbar_timeout_id
= None
60 # Create Image for avatar button
62 self
.xml
.get_widget('PHOTO_button').set_image(image
)
63 self
.xml
.signal_autoconnect(self
)
64 self
.window
.show_all()
66 def update_progressbar(self
):
67 self
.progressbar
.pulse()
68 return True # loop forever
70 def remove_statusbar(self
, message_id
):
71 self
.statusbar
.remove_message(self
.context_id
, message_id
)
72 self
.remove_statusbar_timeout_id
= None
74 def on_profile_window_destroy(self
, widget
):
75 if self
.update_progressbar_timeout_id
is not None:
76 gobject
.source_remove(self
.update_progressbar_timeout_id
)
77 if self
.remove_statusbar_timeout_id
is not None:
78 gobject
.source_remove(self
.remove_statusbar_timeout_id
)
79 del gajim
.interface
.instances
[self
.account
]['profile']
80 if self
.dialog
: # Image chooser dialog
83 def on_profile_window_key_press_event(self
, widget
, event
):
84 if event
.keyval
== gtk
.keysyms
.Escape
:
87 def on_clear_button_clicked(self
, widget
):
89 button
= self
.xml
.get_widget('PHOTO_button')
90 image
= button
.get_image()
91 image
.set_from_pixbuf(None)
93 text_button
= self
.xml
.get_widget('NOPHOTO_button')
95 self
.avatar_encoded
= None
96 self
.avatar_mime_type
= None
98 def on_set_avatar_button_clicked(self
, widget
):
99 def on_ok(widget
, path_to_file
):
101 filesize
= os
.path
.getsize(path_to_file
) # in bytes
104 if os
.path
.isfile(path_to_file
):
105 stat
= os
.stat(path_to_file
)
108 msg
= _('File is empty')
111 msg
= _('File does not exist')
112 if not invalid_file
and filesize
> 16384: # 16 kb
114 pixbuf
= gtk
.gdk
.pixbuf_new_from_file(path_to_file
)
115 # get the image at 'notification size'
116 # and hope that user did not specify in ACE crazy size
117 scaled_pixbuf
= gtkgui_helpers
.get_scaled_pixbuf(pixbuf
,
119 except gobject
.GError
, msg
: # unknown format
120 # msg should be string, not object instance
124 if True: # keep identation
125 dialogs
.ErrorDialog(_('Could not load image'), msg
)
129 path_to_file
= os
.path
.join(gajim
.TMP
,
131 scaled_pixbuf
.save(path_to_file
, 'png')
134 fd
= open(path_to_file
, 'rb')
136 pixbuf
= gtkgui_helpers
.get_pixbuf_from_data(data
)
139 pixbuf
= gtkgui_helpers
.get_scaled_pixbuf(pixbuf
, 'vcard')
140 except AttributeError: # unknown format
141 dialogs
.ErrorDialog(_('Could not load image'))
143 self
.dialog
.destroy()
145 button
= self
.xml
.get_widget('PHOTO_button')
146 image
= button
.get_image()
147 image
.set_from_pixbuf(pixbuf
)
149 text_button
= self
.xml
.get_widget('NOPHOTO_button')
151 self
.avatar_encoded
= base64
.encodestring(data
)
152 # returns None if unknown type
153 self
.avatar_mime_type
= mimetypes
.guess_type(path_to_file
)[0]
156 os
.remove(path_to_file
)
158 gajim
.log
.debug('Cannot remove %s' % path_to_file
)
160 def on_clear(widget
):
161 self
.dialog
.destroy()
163 self
.on_clear_button_clicked(widget
)
165 def on_cancel(widget
):
166 self
.dialog
.destroy()
170 self
.dialog
.present()
172 self
.dialog
= dialogs
.AvatarChooserDialog(on_response_ok
= on_ok
,
173 on_response_cancel
= on_cancel
, on_response_clear
= on_clear
)
175 def on_PHOTO_button_press_event(self
, widget
, event
):
176 '''If right-clicked, show popup'''
177 if event
.button
== 3 and self
.avatar_encoded
: # right click
181 pixbuf
= gtkgui_helpers
.get_avatar_pixbuf_from_cache(self
.jid
,
185 nick
= gajim
.config
.get_per('accounts', self
.account
, 'name')
186 menuitem
= gtk
.ImageMenuItem(gtk
.STOCK_SAVE_AS
)
187 menuitem
.connect('activate',
188 gtkgui_helpers
.on_avatar_save_as_menuitem_activate
,
189 self
.jid
, None, nick
+ '.jpeg')
190 menu
.append(menuitem
)
192 menuitem
= gtk
.ImageMenuItem(gtk
.STOCK_CLEAR
)
193 menuitem
.connect('activate', self
.on_clear_button_clicked
)
194 menu
.append(menuitem
)
195 menu
.connect('selection-done', lambda w
:w
.destroy())
198 menu
.popup(None, None, None, event
.button
, event
.time
)
199 elif event
.button
== 1: # left click
200 self
.on_set_avatar_button_clicked(widget
)
202 def set_value(self
, entry_name
, value
):
204 self
.xml
.get_widget(entry_name
).set_text(value
)
205 except AttributeError:
208 def set_values(self
, vcard_
):
209 button
= self
.xml
.get_widget('PHOTO_button')
210 image
= button
.get_image()
211 text_button
= self
.xml
.get_widget('NOPHOTO_button')
212 if not 'PHOTO' in vcard_
:
214 image
.set_from_pixbuf(None)
217 for i
in vcard_
.keys():
219 pixbuf
, self
.avatar_encoded
, self
.avatar_mime_type
= \
220 vcard
.get_avatar_pixbuf_encoded_mime(vcard_
[i
])
222 image
.set_from_pixbuf(None)
226 pixbuf
= gtkgui_helpers
.get_scaled_pixbuf(pixbuf
, 'vcard')
227 image
.set_from_pixbuf(pixbuf
)
231 if i
== 'ADR' or i
== 'TEL' or i
== 'EMAIL':
232 for entry
in vcard_
[i
]:
236 for j
in entry
.keys():
237 self
.set_value(i
+ add_on
+ '_' + j
+ '_entry', entry
[j
])
238 if isinstance(vcard_
[i
], dict):
239 for j
in vcard_
[i
].keys():
240 self
.set_value(i
+ '_' + j
+ '_entry', vcard_
[i
][j
])
243 self
.xml
.get_widget('DESC_textview').get_buffer().set_text(
246 self
.set_value(i
+ '_entry', vcard_
[i
])
247 if self
.update_progressbar_timeout_id
is not None:
249 self
.statusbar
.remove_message(self
.context_id
, self
.message_id
)
250 self
.message_id
= self
.statusbar
.push(self
.context_id
,
251 _('Information received'))
252 self
.remove_statusbar_timeout_id
= gobject
.timeout_add_seconds(3,
253 self
.remove_statusbar
, self
.message_id
)
254 gobject
.source_remove(self
.update_progressbar_timeout_id
)
255 self
.progressbar
.hide()
256 self
.progressbar
.set_fraction(0)
257 self
.update_progressbar_timeout_id
= None
259 def add_to_vcard(self
, vcard_
, entry
, txt
):
260 '''Add an information to the vCard dictionary'''
261 entries
= entry
.split('_')
263 if len(entries
) == 3: # We need to use lists
264 if entries
[0] not in loc
:
267 for e
in loc
[entries
[0]]:
272 loc
[entries
[0]].append({entries
[1]: '', entries
[2]: txt
})
274 while len(entries
) > 1:
275 if entries
[0] not in loc
:
277 loc
= loc
[entries
[0]]
279 loc
[entries
[0]] = txt
282 def make_vcard(self
):
283 '''make the vCard dictionary'''
284 entries
= ['FN', 'NICKNAME', 'BDAY', 'EMAIL_HOME_USERID', 'URL',
285 'TEL_HOME_NUMBER', 'N_FAMILY', 'N_GIVEN', 'N_MIDDLE', 'N_PREFIX',
286 'N_SUFFIX', 'ADR_HOME_STREET', 'ADR_HOME_EXTADR', 'ADR_HOME_LOCALITY',
287 'ADR_HOME_REGION', 'ADR_HOME_PCODE', 'ADR_HOME_CTRY', 'ORG_ORGNAME',
288 'ORG_ORGUNIT', 'TITLE', 'ROLE', 'TEL_WORK_NUMBER', 'EMAIL_WORK_USERID',
289 'ADR_WORK_STREET', 'ADR_WORK_EXTADR', 'ADR_WORK_LOCALITY',
290 'ADR_WORK_REGION', 'ADR_WORK_PCODE', 'ADR_WORK_CTRY']
293 txt
= self
.xml
.get_widget(e
+ '_entry').get_text().decode('utf-8')
295 vcard_
= self
.add_to_vcard(vcard_
, e
, txt
)
298 buff
= self
.xml
.get_widget('DESC_textview').get_buffer()
299 start_iter
= buff
.get_start_iter()
300 end_iter
= buff
.get_end_iter()
301 txt
= buff
.get_text(start_iter
, end_iter
, 0)
303 vcard_
['DESC'] = txt
.decode('utf-8')
306 if self
.avatar_encoded
:
307 vcard_
['PHOTO'] = {'BINVAL': self
.avatar_encoded
}
308 if self
.avatar_mime_type
:
309 vcard_
['PHOTO']['TYPE'] = self
.avatar_mime_type
312 def on_ok_button_clicked(self
, widget
):
313 if self
.update_progressbar_timeout_id
:
314 # Operation in progress
316 if gajim
.connections
[self
.account
].connected
< 2:
317 dialogs
.ErrorDialog(_('You are not connected to the server'),
318 _('Without a connection you can not publish your contact '
321 vcard_
= self
.make_vcard()
323 if 'NICKNAME' in vcard_
:
324 nick
= vcard_
['NICKNAME']
325 from common
import pep
326 pep
.user_send_nickname(self
.account
, nick
)
328 nick
= gajim
.config
.get_per('accounts', self
.account
, 'name')
329 gajim
.nicks
[self
.account
] = nick
330 gajim
.connections
[self
.account
].send_vcard(vcard_
)
331 self
.message_id
= self
.statusbar
.push(self
.context_id
,
332 _('Sending profile...'))
333 self
.progressbar
.show()
334 self
.update_progressbar_timeout_id
= gobject
.timeout_add(100,
335 self
.update_progressbar
)
337 def vcard_published(self
):
338 if self
.update_progressbar_timeout_id
is not None:
339 gobject
.source_remove(self
.update_progressbar_timeout_id
)
340 self
.update_progressbar_timeout_id
= None
341 self
.window
.destroy()
343 def vcard_not_published(self
):
345 self
.statusbar
.remove_message(self
.context_id
, self
.message_id
)
346 self
.message_id
= self
.statusbar
.push(self
.context_id
,
347 _('Information NOT published'))
348 self
.remove_statusbar_timeout_id
= gobject
.timeout_add_seconds(3,
349 self
.remove_statusbar
, self
.message_id
)
350 if self
.update_progressbar_timeout_id
is not None:
351 gobject
.source_remove(self
.update_progressbar_timeout_id
)
352 self
.progressbar
.set_fraction(0)
353 self
.update_progressbar_timeout_id
= None
354 dialogs
.InformationDialog(_('vCard publication failed'),
355 _('There was an error while publishing your personal information, '
358 def on_cancel_button_clicked(self
, widget
):
359 self
.window
.destroy()