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
This commit is contained in:
parent
cc874227a1
commit
2636e3449f
|
@ -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 @@ class GroupchatControl(ChatControlBase):
|
|||
|
||||
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 @@ class Interface:
|
|||
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 @@ class ProfileWindow:
|
|||
|
||||
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 @@ class ProfileWindow:
|
|||
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 @@ class SignalObject(dbus.service.Object):
|
|||
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 @@ class VcardWindow:
|
|||
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)
|
||||
image = self.xml.get_object('PHOTO_image')
|
||||
image.set_from_pixbuf(pixbuf)
|
||||
image.show()
|
||||
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_surface(surface)
|
||||
image.show()
|
||||
self.xml.get_object('user_avatar_label').show()
|
||||
continue
|
||||
if i in ('ADR', 'TEL', 'EMAIL'):
|
||||
|
|
Loading…
Reference in New Issue