[gnome-contacts] editor: Make sure saving an avatar works again
- From: Niels De Graef <nielsdg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-contacts] editor: Make sure saving an avatar works again
- Date: Thu, 13 Jan 2022 11:27:41 +0000 (UTC)
commit a7d27b5189136a57709c9059a24c0e910c3fb5f7
Author: Niels De Graef <nielsdegraef gmail com>
Date: Thu Jan 13 12:26:56 2022 +0100
editor: Make sure saving an avatar works again
data/ui/contacts-avatar-selector.ui | 5 +-
src/contacts-avatar-selector.vala | 97 +++++++++++++++++++++----------------
src/contacts-avatar.vala | 8 +++
src/contacts-contact-editor.vala | 24 +++++++--
src/contacts-contact-list.vala | 5 +-
5 files changed, 88 insertions(+), 51 deletions(-)
---
diff --git a/data/ui/contacts-avatar-selector.ui b/data/ui/contacts-avatar-selector.ui
index 4872e0d4..6c2a2472 100644
--- a/data/ui/contacts-avatar-selector.ui
+++ b/data/ui/contacts-avatar-selector.ui
@@ -50,8 +50,9 @@
<property name="column_spacing">5</property>
<property name="row_spacing">5</property>
<property name="max_children_per_line">8</property>
- <property name="selection_mode">single</property>
- <property name="homogeneous">False</property>
+ <property name="selection-mode">single</property>
+ <property name="homogeneous">True</property>
+ <property name="activate-on-single-click">False</property>
</object>
</child>
</object>
diff --git a/src/contacts-avatar-selector.vala b/src/contacts-avatar-selector.vala
index 59616c02..dfdb7c56 100644
--- a/src/contacts-avatar-selector.vala
+++ b/src/contacts-avatar-selector.vala
@@ -83,15 +83,40 @@ public class Contacts.AvatarSelector : Gtk.Dialog {
private Xdp.Portal? portal = null;
+ private Gdk.Pixbuf? _selected_avatar = null;
+ public Gdk.Pixbuf? selected_avatar {
+ owned get { return scale_pixbuf_for_avatar_use (this._selected_avatar); }
+ private set { this._selected_avatar = value; }
+ }
+
public AvatarSelector (Individual? individual, Gtk.Window? window = null) {
Object (transient_for: window, use_header_bar: 1);
this.individual = individual;
+ this.thumbnail_grid.selected_children_changed.connect (on_thumbnails_selected);
+ this.thumbnail_grid.child_activated.connect (on_thumbnail_activated);
update_thumbnail_grid ();
this.setup_camera_portal.begin ();
}
+ private void on_thumbnails_selected (Gtk.FlowBox thumbnail_grid) {
+ var selected = thumbnail_grid.get_selected_children ();
+ if (selected != null) {
+ unowned var thumbnail = (Thumbnail) selected.data;
+ this.selected_avatar = thumbnail.source_pixbuf;
+ } else {
+ this.selected_avatar = null;
+ }
+ }
+
+ private void on_thumbnail_activated (Gtk.FlowBox thumbnail_grid,
+ Gtk.FlowBoxChild child) {
+ unowned var thumbnail = (Thumbnail) child;
+ this.selected_avatar = thumbnail.source_pixbuf;
+ this.response (Gtk.ResponseType.ACCEPT);
+ }
+
private async void setup_camera_portal () {
this.portal = new Xdp.Portal ();
@@ -103,7 +128,10 @@ public class Contacts.AvatarSelector : Gtk.Dialog {
}
}
- private Gdk.Pixbuf scale_pixbuf_for_avatar_use (Gdk.Pixbuf pixbuf) {
+ private Gdk.Pixbuf? scale_pixbuf_for_avatar_use (Gdk.Pixbuf? pixbuf) {
+ if (pixbuf == null)
+ return null;
+
int w = pixbuf.get_width ();
int h = pixbuf.get_height ();
@@ -121,42 +149,37 @@ public class Contacts.AvatarSelector : Gtk.Dialog {
return pixbuf.scale_simple (w, h, Gdk.InterpType.HYPER);
}
- private void selected_pixbuf (Gdk.Pixbuf pixbuf) {
- try {
- uint8[] buffer;
- pixbuf.save_to_buffer (out buffer, "png", null);
- var icon = new BytesIcon (new Bytes (buffer));
- // Set the new avatar
- this.individual.change_avatar.begin (icon as LoadableIcon, (obj, res) => {
- try {
- this.individual.change_avatar.end (res);
- } catch (Error e) {
- warning ("Failed to set avatar: %s", e.message);
- Utils.show_error_dialog (_("Failed to set avatar."),
- get_root () as Gtk.Window);
- }
- });
- } catch (GLib.Error e) {
- warning ("Failed to set avatar: %s", e.message);
- Utils.show_error_dialog (_("Failed to set avatar."),
- get_root () as Gtk.Window);
- }
+ /**
+ * Saves the selected avatar as the one that should be used.
+ *
+ * You should probably only do this after the "response" signal
+ * (with ResponseType.ACCEPT)
+ */
+ public async void save_selection () throws GLib.Error {
+ debug ("Saving selected avatar");
+ uint8[] buffer;
+ this.selected_avatar.save_to_buffer (out buffer, "png", null);
+ var icon = new BytesIcon (new Bytes (buffer));
+ // Set the new avatar
+ yield this.individual.change_avatar (icon as LoadableIcon);
}
private void update_thumbnail_grid () {
if (this.individual != null) {
foreach (var p in individual.personas) {
- var widget = new Thumbnail.for_persona (p);
- if (widget.source_pixbuf != null)
- this.thumbnail_grid.insert (widget, -1);
+ var thumbnail = new Thumbnail.for_persona (p);
+ if (thumbnail.source_pixbuf != null) {
+ this.thumbnail_grid.insert (thumbnail, -1);
+ }
}
}
var stock_files = Utils.get_stock_avatars ();
foreach (var file_name in stock_files) {
- var widget = new Thumbnail.for_filename (file_name);
- if (widget.source_pixbuf != null)
- this.thumbnail_grid.insert (widget, -1);
+ var thumbnail = new Thumbnail.for_filename (file_name);
+ if (thumbnail.source_pixbuf != null) {
+ this.thumbnail_grid.insert (thumbnail, -1);
+ }
}
}
@@ -168,19 +191,6 @@ public class Contacts.AvatarSelector : Gtk.Dialog {
// dialog.show ();
}
- public override void response (int response) {
- if (response == Gtk.ResponseType.OK) {
- var selected_children = thumbnail_grid.get_selected_children ();
- if (selected_children != null) {
- unowned var thumbnail = (selected_children.data as Thumbnail);
- if (thumbnail != null)
- selected_pixbuf (scale_pixbuf_for_avatar_use (thumbnail.source_pixbuf));
- }
- }
-
- this.close ();
- }
-
[GtkCallback]
private void on_file_clicked (Gtk.Button button) {
var chooser = new Gtk.FileChooserNative (_("Browse for more pictures"),
@@ -213,14 +223,15 @@ public class Contacts.AvatarSelector : Gtk.Dialog {
get_root () as Gtk.Window);
dialog.response.connect ((response) => {
if (response == Gtk.ResponseType.ACCEPT) {
- var cropped = dialog.create_pixbuf ();
- selected_pixbuf (scale_pixbuf_for_avatar_use (cropped));
+ this.selected_avatar = dialog.create_pixbuf ();
+ this.response (Gtk.ResponseType.ACCEPT);
}
dialog.destroy ();
});
dialog.show ();
} else {
- selected_pixbuf (scale_pixbuf_for_avatar_use (pixbuf));
+ this.selected_avatar = pixbuf;
+ this.response (Gtk.ResponseType.ACCEPT);
}
} catch (GLib.Error e) {
warning ("Failed to set avatar: %s", e.message);
diff --git a/src/contacts-avatar.vala b/src/contacts-avatar.vala
index 3f8b4bab..330fa8ed 100644
--- a/src/contacts-avatar.vala
+++ b/src/contacts-avatar.vala
@@ -75,6 +75,14 @@ public class Contacts.Avatar : Adw.Bin {
}
}
+ /**
+ * Forces a reload of the avatar (e.g. after a property change).
+ */
+ public async void reload () {
+ this.load_avatar_started = false;
+ yield this.load_avatar ();
+ }
+
/**
* Manually set the avatar to the given pixbuf, even if the contact has an avatar.
*/
diff --git a/src/contacts-contact-editor.vala b/src/contacts-contact-editor.vala
index dd2f764b..805b3c0b 100644
--- a/src/contacts-contact-editor.vala
+++ b/src/contacts-contact-editor.vala
@@ -25,8 +25,8 @@ using Folks;
public class Contacts.ContactEditor : Gtk.Box {
private Individual individual;
- private Gtk.Entry name_entry;
- private Avatar avatar;
+ private unowned Gtk.Entry name_entry;
+ private unowned Avatar avatar;
construct {
this.orientation = Gtk.Orientation.VERTICAL;
@@ -50,7 +50,8 @@ public class Contacts.ContactEditor : Gtk.Box {
// Creates the contact's current avatar in a big button on top of the Editor
private Gtk.Widget create_avatar_button () {
- this.avatar = new Avatar (PROFILE_SIZE, this.individual);
+ var avatar = new Avatar (PROFILE_SIZE, this.individual);
+ this.avatar = avatar;
var button = new Gtk.Button ();
button.tooltip_text = _("Change avatar");
@@ -63,7 +64,19 @@ public class Contacts.ContactEditor : Gtk.Box {
// Show the avatar popover when the avatar is clicked
private void on_avatar_button_clicked (Gtk.Button avatar_button) {
var avatar_selector = new AvatarSelector (this.individual, get_root () as Gtk.Window);
- avatar_selector.response.connect (() => {
+ avatar_selector.response.connect ((response) => {
+ if (response == Gtk.ResponseType.ACCEPT) {
+ avatar_selector.save_selection.begin ((obj, res) => {
+ try {
+ avatar_selector.save_selection.end (res);
+ this.avatar.set_pixbuf (avatar_selector.selected_avatar);
+ } catch (Error e) {
+ warning ("Failed to set avatar: %s", e.message);
+ Utils.show_error_dialog (_("Failed to set avatar."),
+ get_root () as Gtk.Window);
+ }
+ });
+ }
avatar_selector.destroy ();
});
avatar_selector.show ();
@@ -72,7 +85,8 @@ public class Contacts.ContactEditor : Gtk.Box {
// Creates the big name entry on the top
private Gtk.Widget create_name_entry () {
NameDetails name = this.individual as NameDetails;
- this.name_entry = new Gtk.Entry ();
+ var entry = new Gtk.Entry ();
+ this.name_entry = entry;
this.name_entry.hexpand = true;
this.name_entry.valign = Gtk.Align.CENTER;
this.name_entry.input_purpose = Gtk.InputPurpose.NAME;
diff --git a/src/contacts-contact-list.vala b/src/contacts-contact-list.vala
index 247e7aaf..edce740d 100644
--- a/src/contacts-contact-list.vala
+++ b/src/contacts-contact-list.vala
@@ -380,7 +380,10 @@ public class Contacts.ContactList : Adw.Bin {
}
private void on_contact_changed (Object obj, ParamSpec pspec) {
- //TODO: Update also the Avatar
+ if (pspec.get_name () == "avatar") {
+ this.avatar.reload ();
+ }
+ // Always update the label, since it can depend on a lot of properties
this.label.set_text (this.individual.display_name);
changed ();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]