we can now save avatars on HD where we want (right click on image). Fixes #1817
This commit is contained in:
parent
d174cf89c7
commit
3e1dd88ee0
|
@ -17,6 +17,7 @@
|
|||
<property name="type_hint">GDK_WINDOW_TYPE_HINT_NORMAL</property>
|
||||
<property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
|
||||
<property name="focus_on_map">True</property>
|
||||
<property name="urgency_hint">False</property>
|
||||
<signal name="destroy" handler="on_vcard_information_window_destroy" last_modification_time="Sun, 24 Jul 2005 19:35:15 GMT"/>
|
||||
<signal name="key_press_event" handler="on_vcard_information_window_key_press_event" last_modification_time="Thu, 07 Apr 2005 10:06:13 GMT"/>
|
||||
|
||||
|
@ -2320,6 +2321,12 @@
|
|||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">0</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkEventBox" id="PHOTO_eventbox">
|
||||
<property name="visible">True</property>
|
||||
<property name="visible_window">True</property>
|
||||
<property name="above_child">False</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImage" id="PHOTO_image">
|
||||
<property name="visible">True</property>
|
||||
|
@ -2328,6 +2335,8 @@
|
|||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">True</property>
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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))
|
||||
|
|
24
src/vcard.py
24
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'),
|
||||
|
|
Loading…
Reference in New Issue