diff --git a/data/glade/vcard_information_window.glade b/data/glade/vcard_information_window.glade
index f33143daf..de8069b69 100644
--- a/data/glade/vcard_information_window.glade
+++ b/data/glade/vcard_information_window.glade
@@ -17,6 +17,7 @@
GDK_WINDOW_TYPE_HINT_NORMAL
GDK_GRAVITY_NORTH_WEST
True
+ False
@@ -2321,12 +2322,20 @@
0
-
+
True
- 0.5
- 0.5
- 0
- 0
+ True
+ False
+
+
+
+ True
+ 0.5
+ 0.5
+ 0
+ 0
+
+
0
diff --git a/src/chat_control.py b/src/chat_control.py
index c1092fea8..a0862f95b 100644
--- a/src/chat_control.py
+++ b/src/chat_control.py
@@ -754,10 +754,12 @@ class ChatControl(ChatControlBase):
id = widget.connect('enter-notify-event', self.on_avatar_eventbox_enter_notify_event)
self.handlers[id] = widget
- widget = self.xml.get_widget('avatar_eventbox')
id = widget.connect('leave-notify-event', self.on_avatar_eventbox_leave_notify_event)
self.handlers[id] = widget
+ id = widget.connect('button-press-event', self.on_avatar_eventbox_button_press_event)
+ self.handlers[id] = widget
+
widget = self.xml.get_widget('gpg_togglebutton')
id = widget.connect('clicked', self.on_toggle_gpg_togglebutton)
self.handlers[id] = widget
@@ -803,6 +805,23 @@ class ChatControl(ChatControlBase):
if self.show_bigger_avatar_timeout_id is not None:
gobject.source_remove(self.show_bigger_avatar_timeout_id)
+ def on_avatar_eventbox_button_press_event(self, widget, event):
+ '''If right-clicked, show popup'''
+ if event.button == 3: # right click
+ menu = gtk.Menu()
+ menuitem = gtk.ImageMenuItem(gtk.STOCK_SAVE_AS)
+ id = menuitem.connect('activate',
+ gtkgui_helpers.on_avatar_save_as_menuitem_activate,
+ self.contact.jid, self.account, self.contact.name + '.jpeg')
+ self.handlers[id] = menuitem
+ menu.append(menuitem)
+ menu.show_all()
+ menu.connect('selection-done', lambda w:w.destroy())
+ # show the menu
+ menu.show_all()
+ menu.popup(None, None, None, event.button, event.time)
+ return True
+
def _on_window_motion_notify(self, widget, event):
'''it gets called no matter if it is the active window or not'''
if self.parent_win.get_active_jid() == self.contact.jid:
diff --git a/src/gtkgui_helpers.py b/src/gtkgui_helpers.py
index e6657b04d..35bbfbb1d 100644
--- a/src/gtkgui_helpers.py
+++ b/src/gtkgui_helpers.py
@@ -25,6 +25,7 @@ import os
import sys
import vcard
+import dialogs
HAS_PYWIN32 = True
@@ -666,3 +667,70 @@ def get_possible_button_event(event):
def destroy_widget(widget):
widget.destroy()
+
+def on_avatar_save_as_menuitem_activate(widget, jid, account,
+default_name = ''):
+ def on_ok(widget):
+ def on_ok2(widget, file_path, pixbuf):
+ pixbuf.save(file_path, 'jpeg')
+ dialog2.destroy()
+ dialog.destroy()
+
+ file_path = dialog.get_filename()
+ file_path = decode_filechooser_file_paths((file_path,))[0]
+ if os.path.exists(file_path):
+ dialog2 = dialogs.FTOverwriteConfirmationDialog(
+ _('This file already exists'), _('What do you want to do?'),
+ False)
+ dialog2.set_transient_for(dialog)
+ dialog2.set_destroy_with_parent(True)
+ response = dialog2.get_response()
+ if response < 0:
+ return
+
+ # Get pixbuf
+ pixbuf = None
+ is_fake = False
+ if gajim.contacts.is_pm_from_jid(account, jid):
+ is_fake = True
+ pixbuf = get_avatar_pixbuf_from_cache(jid, is_fake)
+
+ ext = file_path.split('.')[-1]
+ type_ = ''
+ if not ext:
+ # Silently save as Jpeg image
+ file_path += '.jpeg'
+ type_ = 'jpeg'
+ elif ext == 'jpg':
+ type_ = 'jpeg'
+ else:
+ type_ = ext
+
+ # Save image
+ try:
+ pixbuf.save(file_path, type_)
+ except:
+ os.remove(file_path)
+ new_file_path = '.'.join(file_path.split('.')[:-1]) + '.jpeg'
+ dialog2 = dialogs.ConfirmationDialog(_('Extension not supported'),
+ _('Image cannot be saved in %(type)s format. Save as %(new_filename)s?') % {'type': type_, 'new_filename': new_file_path},
+ on_response_ok = (on_ok2, new_file_path, pixbuf))
+ else:
+ dialog.destroy()
+
+ def on_cancel(widget):
+ dialog.destroy()
+
+ dialog = dialogs.FileChooserDialog(
+ title_text = _('Save Image as...'),
+ action = gtk.FILE_CHOOSER_ACTION_SAVE,
+ buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
+ gtk.STOCK_SAVE, gtk.RESPONSE_OK),
+ default_response = gtk.RESPONSE_OK,
+ current_folder = gajim.config.get('last_save_dir'),
+ on_response_ok = on_ok,
+ on_response_cancel = on_cancel)
+
+ dialog.set_current_name(default_name)
+ dialog.connect('delete-event', lambda widget, event:
+ on_cancel(widget))
diff --git a/src/vcard.py b/src/vcard.py
index 91cd1c20b..2769722a8 100644
--- a/src/vcard.py
+++ b/src/vcard.py
@@ -80,6 +80,7 @@ class VcardWindow:
self.is_fake = is_fake
self.avatar_mime_type = None
self.avatar_encoded = None
+ self.avatar_save_as_id = None
if vcard: # we view/edit our own vcard
self.jid = contact
@@ -155,6 +156,8 @@ class VcardWindow:
# empty the image
self.xml.get_widget('PHOTO_image').set_from_pixbuf(None)
self.avatar_encoded = None
+ self.xml.get_widget('PHOTO_eventbox').disconnect(self.avatar_save_as_id)
+ self.avatar_save_as_id = None
def on_set_avatar_button_clicked(self, widget):
f = None
@@ -204,6 +207,21 @@ class VcardWindow:
self.dialog = dialogs.ImageChooserDialog(on_response_ok = on_ok)
+ def on_PHOTO_eventbox_button_press_event(self, widget, event):
+ '''If right-clicked, show popup'''
+ if event.button == 3: # right click
+ menu = gtk.Menu()
+ menuitem = gtk.ImageMenuItem(gtk.STOCK_SAVE_AS)
+ menuitem.connect('activate',
+ gtkgui_helpers.on_avatar_save_as_menuitem_activate,
+ self.contact.jid, self.account, self.contact.name + '.jpeg')
+ menu.append(menuitem)
+ menu.show_all()
+ menu.connect('selection-done', lambda w:w.destroy())
+ # show the menu
+ menu.show_all()
+ menu.popup(None, None, None, event.button, event.time)
+
def set_value(self, entry_name, value):
try:
self.xml.get_widget(entry_name).set_text(value)
@@ -220,6 +238,9 @@ class VcardWindow:
image = self.xml.get_widget('PHOTO_image')
pixbuf = gtkgui_helpers.get_scaled_pixbuf(pixbuf, 'vcard')
image.set_from_pixbuf(pixbuf)
+ eventbox = self.xml.get_widget('PHOTO_eventbox')
+ self.avatar_save_as_id = eventbox.connect('button-press-event',
+ self.on_PHOTO_eventbox_button_press_event)
continue
if i == 'ADR' or i == 'TEL' or i == 'EMAIL':
for entry in vcard[i]:
@@ -453,6 +474,9 @@ class VcardWindow:
self.xml.get_widget(e + '_entry').set_text('')
self.xml.get_widget('DESC_textview').get_buffer().set_text('')
self.xml.get_widget('PHOTO_image').set_from_pixbuf(None)
+ self.xml.get_widget('PHOTO_eventbox').disconnect(
+ self.avatar_save_as_id)
+ self.avatar_save_as_id = None
gajim.connections[self.account].request_vcard(self.jid)
else:
dialogs.ErrorDialog(_('You are not connected to the server'),