Commit a1db7b08 authored by Philip Withnall's avatar Philip Withnall
Browse files

core: Add AvatarDetails.change_avatar()

This allows the avatar of an implementing class to be changed asynchronously
with proper error notification.

Helps: bgo#657510
parent e390bdd7
......@@ -272,8 +272,16 @@ public class Edsf.PersonaStore : Folks.PersonaStore
}
else if (k == Folks.PersonaStore.detail_key (PersonaDetail.AVATAR))
{
var avatar = (LoadableIcon?) v.get_object ();
yield this._set_contact_avatar (contact, avatar);
try
{
var avatar = (LoadableIcon?) v.get_object ();
yield this._set_contact_avatar (contact, avatar);
}
catch (PropertyError e1)
{
warning ("Couldn't set avatar on the EContact: %s",
e1.message);
}
}
else if (k == Folks.PersonaStore.detail_key (
PersonaDetail.IM_ADDRESSES))
......@@ -683,6 +691,7 @@ public class Edsf.PersonaStore : Folks.PersonaStore
}
internal async void _set_avatar (Edsf.Persona persona, LoadableIcon? avatar)
throws PropertyError
{
/* Return early if there will be no change */
if ((persona.avatar == null && avatar == null) ||
......@@ -697,9 +706,13 @@ public class Edsf.PersonaStore : Folks.PersonaStore
yield this._set_contact_avatar (contact, avatar);
yield this._addressbook.modify_contact (contact, null);
}
catch (GLib.Error e)
catch (PropertyError e1)
{
throw e1;
}
catch (GLib.Error e2)
{
GLib.warning ("Can't update avatar: %s\n", e.message);
throw this.e_client_error_to_property_error ("avatar", e2);
}
}
......@@ -867,7 +880,7 @@ public class Edsf.PersonaStore : Folks.PersonaStore
}
private async void _set_contact_avatar (E.Contact contact,
LoadableIcon? avatar)
LoadableIcon? avatar) throws PropertyError
{
if (avatar == null)
{
......@@ -905,8 +918,10 @@ public class Edsf.PersonaStore : Folks.PersonaStore
}
catch (GLib.Error e1)
{
warning ("Couldn't set avatar on the EContact : %s",
e1.message);
/* Loading/Reading the avatar failed. */
throw new PropertyError.INVALID_VALUE (
/* Translators: the parameter is an error message. */
_("Can't update avatar: %s"), e1.message);
}
}
}
......
......@@ -267,13 +267,20 @@ public class Edsf.Persona : Folks.Persona,
public LoadableIcon? avatar
{
get { return this._avatar; }
set
set { this.change_avatar.begin (value); }
}
/**
* {@inheritDoc}
*
* @since UNRELEASED
*/
public async void change_avatar (LoadableIcon? avatar) throws PropertyError
{
if (this._avatar == null ||
!this._avatar.equal (avatar))
{
if (this._avatar == null ||
!this._avatar.equal (value))
{
((Edsf.PersonaStore) this.store)._set_avatar (this, value);
}
yield ((Edsf.PersonaStore) this.store)._set_avatar (this, avatar);
}
}
......
......@@ -69,6 +69,8 @@ public class Swf.Persona : Folks.Persona,
get { return this._writeable_properties; }
}
private LoadableIcon? _avatar = null;
/**
* An avatar for the Persona.
*
......@@ -76,7 +78,12 @@ public class Swf.Persona : Folks.Persona,
*
* @since 0.6.0
*/
public LoadableIcon? avatar { get; private set; }
[CCode (notify = false)]
public LoadableIcon? avatar
{
get { return this._avatar; }
set { this.change_avatar.begin (value); } /* not writeable */
}
/**
* {@inheritDoc}
......@@ -292,12 +299,16 @@ public class Swf.Persona : Folks.Persona,
if (avatar_path != null)
{
var icon = new FileIcon (File.new_for_path (avatar_path));
if (this.avatar == null || !this.avatar.equal (icon))
this.avatar = icon;
if (this._avatar == null || !this._avatar.equal (icon))
{
this._avatar = icon;
this.notify_property ("avatar");
}
}
else
{
this.avatar = null;
this._avatar = null;
this.notify_property ("avatar");
}
var structured_name = new StructuredName.simple (
......
......@@ -66,6 +66,8 @@ public class Tpf.Persona : Folks.Persona,
*/
public bool is_in_contact_list { get; set; }
private LoadableIcon? _avatar = null;
/**
* An avatar for the Persona.
*
......@@ -73,7 +75,12 @@ public class Tpf.Persona : Folks.Persona,
*
* @since 0.6.0
*/
public LoadableIcon? avatar { get; private set; }
[CCode (notify = false)]
public LoadableIcon? avatar
{
get { return this._avatar; }
set { this.change_avatar.begin (value); } /* not writeable */
}
/**
* The Persona's presence type.
......@@ -423,7 +430,7 @@ public class Tpf.Persona : Folks.Persona,
this._alias = alias;
this._is_favourite = is_favourite;
this.is_in_contact_list = is_in_contact_list;
this.avatar = avatar;
this._avatar = avatar;
// Make the persona appear offline
this.presence_type = PresenceType.OFFLINE;
......@@ -506,7 +513,10 @@ public class Tpf.Persona : Folks.Persona,
if (file != null)
icon = new FileIcon (file);
if (this.avatar == null || icon == null || !this.avatar.equal (icon))
this.avatar = (LoadableIcon) icon;
if (this._avatar == null || icon == null || !this._avatar.equal (icon))
{
this._avatar = (LoadableIcon) icon;
this.notify_property ("avatar");
}
}
}
......@@ -142,13 +142,21 @@ public class Trf.Persona : Folks.Persona,
*
* @since 0.6.0
*/
[CCode (notify = false)]
public LoadableIcon? avatar
{
get { return this._avatar; }
public set
{
((Trf.PersonaStore) this.store)._set_avatar (this, value);
}
set { this.change_avatar.begin (value); }
}
/**
* {@inheritDoc}
*
* @since UNRELEASED
*/
public async void change_avatar (LoadableIcon? avatar) throws PropertyError
{
yield ((Trf.PersonaStore) this.store)._set_avatar (this, avatar);
}
private StructuredName _structured_name;
......
/*
* Copyright (C) 2010 Collabora Ltd.
* Copyright (C) 2011 Philip Withnall
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
......@@ -16,6 +17,7 @@
*
* Authors:
* Travis Reitter <travis.reitter@collabora.co.uk>
* Philip Withnall <philip@tecnocode.co.uk>
*/
using GLib;
......@@ -36,4 +38,24 @@ public interface Folks.AvatarDetails : Object
* @since 0.6.0
*/
public abstract LoadableIcon? avatar { get; set; }
/**
* Change the contact's avatar.
*
* It's preferred to call this rather than setting
* {@link AvatarDetails.avatar} directly, as this method gives error
* notification and will only return once the avatar has been written to the
* relevant backing store (or the operation's failed).
*
* @param avatar the new avatar (or `null` to unset the avatar)
* @throws PropertyError if setting the avatar failed
* @since UNRELEASED
*/
public virtual async void change_avatar (LoadableIcon? avatar)
throws PropertyError
{
/* Default implementation. */
throw new PropertyError.NOT_WRITEABLE (
_("Avatar is not writeable on this contact."));
}
}
......@@ -115,12 +115,19 @@ public class Folks.Individual : Object,
*/
public TrustLevel trust_level { get; private set; }
private LoadableIcon? _avatar = null;
/**
* {@inheritDoc}
*
* @since 0.6.0
*/
public LoadableIcon? avatar { get; private set; }
[CCode (notify = false)]
public LoadableIcon? avatar
{
get { return this._avatar; }
set { this.change_avatar.begin (value); } /* not writeable */
}
/**
* {@inheritDoc}
......@@ -1072,8 +1079,11 @@ public class Folks.Individual : Object,
}
/* only notify if the value has changed */
if (this.avatar == null || !this.avatar.equal (avatar))
this.avatar = avatar;
if (this._avatar == null || !this._avatar.equal (avatar))
{
this._avatar = avatar;
this.notify_property ("avatar");
}
}
private void _update_trust_level ()
......
......@@ -8,6 +8,7 @@ backends/telepathy/lib/tpf-persona-store.vala
backends/telepathy/lib/tpf-persona.vala
backends/tracker/lib/trf-persona-store.vala
folks/alias-details.vala
folks/avatar-details.vala
folks/backend-store.vala
folks/im-details.vala
folks/individual-aggregator.vala
......
......@@ -7,6 +7,7 @@ backends/telepathy/lib/tpf-persona.c
backends/tracker/lib/trf-persona-store.c
docs/gtk-doc/folks-telepathy/ccomments/tp-lowlevel.c
folks/alias-details.c
folks/avatar-details.c
folks/backend-store.c
folks/im-details.c
folks/individual-aggregator.c
......
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