=?utf-8?q?=5Bfolks=5D_Bug_633781_=E2=80=94_Allow_to_set_avatar_on_individ?= =?utf-8?q?uals?=
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [folks] Bug 633781 â Allow to set avatar on individuals
- Date: Tue, 13 Sep 2011 19:15:26 +0000 (UTC)
commit 0737c2d78c4041bb211bd005d28a6960babddb70
Author: Philip Withnall <philip tecnocode co uk>
Date: Fri Aug 12 12:18:16 2011 +0200
Bug 633781 â Allow to set avatar on individuals
Make Individual.avatar writeable and write new avatars back to the personas
from writeable persona stores in an individual.
Closes: bgo#633781
NEWS | 5 ++
folks/individual.vala | 64 +++++++++++++++++++
tests/eds/set-avatar.vala | 154 ++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 222 insertions(+), 1 deletions(-)
---
diff --git a/NEWS b/NEWS
index 881613b..21af72f 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,11 @@ Bugs fixed:
* Bug 658874 â Typo?
* Bug 658730 â ngettext (Plural forms) needed for
"Imported %u buddies from '%s'."
+* Bug 633781 â Allow to set avatar on individuals
+
+API changes:
+* Individual.avatar is now settable using Individual.change_avatar() (not new
+ API, but it no longer always returns an error)
Overview of changes from libfolks 0.6.2 to libfolks 0.6.2.1
===========================================================
diff --git a/folks/individual.vala b/folks/individual.vala
index 59548ee..f9ae1bc 100644
--- a/folks/individual.vala
+++ b/folks/individual.vala
@@ -145,6 +145,70 @@ public class Folks.Individual : Object,
set { this.change_avatar.begin (value); } /* not writeable */
}
+ /*
+ * Change the individual's avatar.
+ *
+ * It's preferred to call this rather than setting { link Individual.avatar}
+ * directly, as this method gives error notification and will only return once
+ * the avatar has been written to the relevant backing stores (or the
+ * operation's failed).
+ *
+ * Setting this property is only guaranteed to succeed (and be written to
+ * the backing store) if
+ * { link IndividualAggregator.ensure_individual_property_writeable} has been
+ * called successfully on the individual for the property name `avatar`.
+ *
+ * @param avatar the new avatar (or `null` to unset the avatar)
+ * @throws PropertyError if setting the avatar failed
+ * @since UNRELEASED
+ */
+ public async void change_avatar (LoadableIcon? avatar) throws PropertyError
+ {
+ if ((this._avatar != null && this._avatar.equal (avatar)) ||
+ (this._avatar == null && avatar == null))
+ {
+ return;
+ }
+
+ debug ("Setting avatar of individual '%s' to '%p'â", this.id, avatar);
+
+ PropertyError? persona_error = null;
+ var avatar_changed = false;
+
+ /* Try to write it to only the writeable Personas which have the
+ * "avatar" property as writeable. */
+ foreach (var p in this._persona_set)
+ {
+ var a = p as AvatarDetails;
+ if (a != null && p.store.is_writeable == true &&
+ "avatar" in p.writeable_properties)
+ {
+ try
+ {
+ yield a.change_avatar (avatar);
+ debug (" written to writeable persona '%s'", p.uid);
+ avatar_changed = true;
+ }
+ catch (PropertyError e)
+ {
+ /* Store the first error so we can throw it if setting the
+ * avatar fails on every other persona. */
+ if (persona_error == null)
+ {
+ persona_error = e;
+ }
+ }
+ }
+ }
+
+ /* Failure? */
+ if (avatar_changed == false)
+ {
+ assert (persona_error != null);
+ throw persona_error;
+ }
+ }
+
/**
* { inheritDoc}
*/
diff --git a/tests/eds/set-avatar.vala b/tests/eds/set-avatar.vala
index 55559e3..90e8b20 100644
--- a/tests/eds/set-avatar.vala
+++ b/tests/eds/set-avatar.vala
@@ -38,6 +38,8 @@ public class SetAvatarTests : Folks.TestCase
this._eds_backend = new EdsTest.Backend ();
this.add_test ("setting avatar on e-d-s persona", this.test_set_avatar);
+ this.add_test ("setting avatar on e-d-s individual",
+ this.test_set_individual_avatar);
}
public override void set_up ()
@@ -70,7 +72,7 @@ public class SetAvatarTests : Folks.TestCase
this._test_set_avatar_async ();
- Timeout.add_seconds (5, () => {
+ var timeout_id = Timeout.add_seconds (5, () => {
this._main_loop.quit ();
assert_not_reached ();
});
@@ -79,6 +81,10 @@ public class SetAvatarTests : Folks.TestCase
assert (this._found_before_update);
assert (this._found_after_update);
+
+ Source.remove (timeout_id);
+ this._aggregator = null;
+ this._main_loop = null;
}
private async void _test_set_avatar_async ()
@@ -150,6 +156,152 @@ public class SetAvatarTests : Folks.TestCase
});
}
}
+
+ void test_set_individual_avatar ()
+ {
+ var c1 = new Gee.HashMap<string, Value?> ();
+ this._main_loop = new GLib.MainLoop (null, false);
+ var avatar_path = Environment.get_variable ("AVATAR_FILE_PATH");
+ this._avatar = new FileIcon (File.new_for_path (avatar_path));
+ Value? v;
+
+ this._found_before_update = false;
+ this._found_after_update = false;
+
+ this._eds_backend.reset ();
+
+ v = Value (typeof (string));
+ v.set_string ("John McClane");
+ c1.set ("full_name", (owned) v);
+ this._eds_backend.add_contact (c1);
+
+ this._test_set_individual_avatar_async ();
+
+ var timeout_id = Timeout.add_seconds (5, () =>
+ {
+ this._main_loop.quit ();
+ assert_not_reached ();
+ });
+
+ this._main_loop.run ();
+
+ assert (this._found_before_update);
+ assert (this._found_after_update);
+
+ Source.remove (timeout_id);
+ this._aggregator = null;
+ this._main_loop = null;
+ }
+
+ private async void _test_set_individual_avatar_async ()
+ {
+ yield this._eds_backend.commit_contacts_to_addressbook ();
+
+ var store = BackendStore.dup ();
+ yield store.prepare ();
+
+ this._aggregator = new IndividualAggregator ();
+ this._aggregator.individuals_changed_detailed.connect ((changes) =>
+ {
+ var added = changes.get_values ();
+ var removed = changes.get_keys ();
+
+ foreach (Individual i in added)
+ {
+ assert (i != null);
+
+ var name = (Folks.NameDetails) i;
+
+ if (name.full_name == "John McClane")
+ {
+ i.notify["avatar"].connect (
+ this._notify_individual_avatar_cb);
+ this._found_before_update = true;
+
+ /* Just set the avatar on the individual */
+ i.change_avatar.begin (this._avatar, (obj, res) =>
+ {
+ try
+ {
+ i.change_avatar.end (res);
+
+ assert (this._found_before_update == true);
+ assert (this._found_after_update == true);
+
+ this._check_individual_has_avatar.begin (i,
+ (obj, res) =>
+ {
+ assert (
+ this._check_individual_has_avatar.end (res)
+ == true);
+
+ this._main_loop.quit ();
+ });
+ }
+ catch (PropertyError e)
+ {
+ critical ("Unexpected error changing avatar: %s",
+ e.message);
+ }
+ });
+ }
+ }
+
+ assert (removed.size == 1);
+
+ foreach (var i in removed)
+ {
+ assert (i == null);
+ }
+ });
+
+ try
+ {
+ yield this._aggregator.prepare ();
+ }
+ catch (GLib.Error e)
+ {
+ GLib.warning ("Error when calling prepare: %s\n", e.message);
+ }
+ }
+
+ private void _notify_individual_avatar_cb (Object individual_obj,
+ ParamSpec ps)
+ {
+ /* Note: we can't check whether the avatar's correct here, as that's an
+ * async operation, and if we start that operation in this signal
+ * callback it'll probably end up finishing after the rest of the code in
+ * _test_set_individual_avatar_async() has already failed. */
+ this._found_after_update = true;
+ }
+
+ private async bool _check_individual_has_avatar (Individual i)
+ {
+ var name = (Folks.NameDetails) i;
+
+ if (name.full_name == "John McClane")
+ {
+ var individual_equal = yield TestUtils.loadable_icons_content_equal (
+ i.avatar, this._avatar, -1);
+
+ if (individual_equal == true)
+ {
+ foreach (var p in i.personas)
+ {
+ var persona_equal =
+ yield TestUtils.loadable_icons_content_equal (
+ (p as AvatarDetails).avatar, this._avatar, -1);
+
+ if (p.store.type_id == "eds" && persona_equal == true)
+ {
+ return true;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
}
public int main (string[] args)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]