Commit 2636e344 authored by Philipp Hörist's avatar Philipp Hörist
Browse files

Refactor avatar publishing

- Publish avatars with a size of 200x200
- Add AvatarSize.PUBLISH so we can easily change it in the future
- Dont upscale small avatars on publish
- Use surfaces for displaying the avatar in ProfileWindow and VcardWindow
because this scales correctly on HiDPI screens
parent cc874227
......@@ -33,9 +33,9 @@ class AvatarSize(IntEnum):
ROSTER = 32
CHAT = 48
NOTIFICATION = 48
PROFILE = 64
TOOLTIP = 125
VCARD = 200
PUBLISH = 200
class ArchiveState(IntEnum):
NEVER = 0
......
......@@ -768,9 +768,7 @@ def _on_execute_command(self, action, param):
def _on_upload_avatar(self, action, param):
def _on_accept(filename):
with open(filename, 'rb') as file:
data = file.read()
sha = app.interface.save_avatar(data, publish=True)
sha = app.interface.save_avatar(filename, publish=True)
if sha is None:
dialogs.ErrorDialog(
_('Could not load image'),
......
......@@ -440,11 +440,22 @@ def scale_with_ratio(size, width, height):
return size, size
if height > width:
ratio = height / float(width)
return int(size / ratio), size
return int(size / ratio), size
else:
ratio = width / float(height)
return size, int(size / ratio)
def scale_pixbuf(pixbuf, size):
width, height = scale_with_ratio(size,
pixbuf.get_width(),
pixbuf.get_height())
return pixbuf.scale_simple(width, height,
GdkPixbuf.InterpType.BILINEAR)
def scale_pixbuf_from_data(data, size):
pixbuf = get_pixbuf_from_data(data)
return scale_pixbuf(pixbuf, size)
def on_avatar_save_as_menuitem_activate(widget, avatar, default_name=''):
from gajim import dialogs
def on_continue(response, file_path):
......
......@@ -2400,16 +2400,36 @@ def update_avatar(account=None, jid=None, contact=None, room_avatar=False):
UpdateGCAvatarEvent(None, contact=contact))
def save_avatar(self, data, publish=False):
"""
Save an avatar to the harddisk
:param data: publish=False data must be bytes
publish=True data must be a path to a file
:param publish: If publish is True, the method scales the file
to AvatarSize.PUBLISH size before saving
returns SHA1 value of the avatar or None on error
"""
if data is None:
return
if publish:
with open(data, 'rb') as file:
data = file.read()
pixbuf = gtkgui_helpers.get_pixbuf_from_data(data)
if pixbuf is None:
return
pixbuf = pixbuf.scale_simple(AvatarSize.PROFILE,
AvatarSize.PROFILE,
GdkPixbuf.InterpType.BILINEAR)
width = pixbuf.get_width()
height = pixbuf.get_height()
if width > AvatarSize.PUBLISH or height > AvatarSize.PUBLISH:
# Scale only down, never up
width, height = gtkgui_helpers.scale_with_ratio(
AvatarSize.PUBLISH, width, height)
pixbuf = pixbuf.scale_simple(width,
height,
GdkPixbuf.InterpType.BILINEAR)
publish_path = os.path.join(
configpaths.get('AVATAR'), 'temp_publish')
pixbuf.savev(publish_path, 'png', [], [])
......
......@@ -124,9 +124,7 @@ def _clear_photo(self, widget):
def on_set_avatar_button_clicked(self, widget):
def on_ok(path_to_file):
with open(path_to_file, 'rb') as file:
data = file.read()
sha = app.interface.save_avatar(data, publish=True)
sha = app.interface.save_avatar(path_to_file, publish=True)
if sha is None:
dialogs.ErrorDialog(
_('Could not load image'), transient_for=self.window)
......@@ -224,13 +222,16 @@ def set_values(self, vcard_):
self.avatar_sha = hashlib.sha1(photo_decoded).hexdigest()
if 'TYPE' in vcard_[i]:
self.avatar_mime_type = vcard_[i]['TYPE']
pixbuf = gtkgui_helpers.get_pixbuf_from_data(photo_decoded)
if pixbuf is None:
continue
pixbuf = pixbuf.scale_simple(
AvatarSize.PROFILE, AvatarSize.PROFILE,
GdkPixbuf.InterpType.BILINEAR)
image.set_from_pixbuf(pixbuf)
scale = self.window.get_scale_factor()
surface = app.interface.get_avatar(
self.avatar_sha, AvatarSize.VCARD, scale)
if surface is None:
pixbuf = gtkgui_helpers.scale_pixbuf_from_data(
photo_decoded, AvatarSize.VCARD)
surface = Gdk.cairo_surface_create_from_pixbuf(pixbuf,
scale)
image.set_from_surface(surface)
button.show()
remove_avatar.show()
text_button.hide()
......
......@@ -825,9 +825,7 @@ def change_avatar(self, picture, account):
else:
invalid_file = True
if not invalid_file and filesize < 16384:
with open(picture, 'rb') as fd:
data = fd.read()
sha = app.interface.save_avatar(data, publish=True)
sha = app.interface.save_avatar(picture, publish=True)
if sha is None:
return
app.config.set_per('accounts', self.name, 'avatar_sha', sha)
......
......@@ -218,16 +218,17 @@ def _set_values(self, vcard, jid):
except binascii.Error as error:
app.log('avatar').warning('Invalid avatar for %s: %s', jid, error)
continue
pixbuf = gtkgui_helpers.get_pixbuf_from_data(photo_decoded)
if pixbuf is None:
continue
pixbuf = pixbuf.scale_simple(
AvatarSize.PROFILE, AvatarSize.PROFILE,
GdkPixbuf.InterpType.BILINEAR)
self.avatar = pixbuf
pixbuf = gtkgui_helpers.scale_pixbuf(pixbuf, AvatarSize.VCARD)
surface = Gdk.cairo_surface_create_from_pixbuf(
pixbuf, self.window.get_scale_factor())
image = self.xml.get_object('PHOTO_image')
image.set_from_pixbuf(pixbuf)
image.set_from_surface(surface)
image.show()
self.avatar = pixbuf
self.xml.get_object('user_avatar_label').show()
continue
if i in ('ADR', 'TEL', 'EMAIL'):
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment