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
					
				
					 7 changed files with 56 additions and 27 deletions
				
			
		|  | @ -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…
	
	Add table
		
		Reference in a new issue