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'),