Commit 073dc310 authored by Philip Withnall's avatar Philip Withnall
Browse files

core: Add FavouriteDetails.change_is_favourite()

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

Helps: bgo#657510
parent b5d1fdef
......@@ -1972,17 +1972,16 @@ public class Tpf.PersonaStore : Folks.PersonaStore
* Telepathy logger service, so may fail if that connection is not present.
*/
internal async void change_is_favourite (Folks.Persona persona,
bool is_favourite)
bool is_favourite) throws PropertyError
{
/* It's possible for us to not be able to connect to the logger;
* see _connection_ready_cb() */
if (this._logger == null)
{
warning (
throw new PropertyError.UNKNOWN_ERROR (
/* Translators: "telepathy-logger" is the name of an application,
* and should not be translated. */
_("Failed to change favorite without a connection to the telepathy-logger service."));
return;
}
try
......@@ -1998,7 +1997,8 @@ public class Tpf.PersonaStore : Folks.PersonaStore
}
catch (GLib.Error e)
{
warning (_("Failed to change a persona's favorite status."));
throw new PropertyError.UNKNOWN_ERROR (
_("Failed to change a persona's favorite status."));
}
}
......
......@@ -163,19 +163,33 @@ public class Tpf.Persona : Folks.Persona,
*
* See {@link Folks.FavouriteDetails.is_favourite}.
*/
[CCode (notify = false)]
public bool is_favourite
{
get { return this._is_favourite; }
set { this.change_is_favourite.begin (value); }
}
set
/**
* {@inheritDoc}
*
* @since UNRELEASED
*/
public async void change_is_favourite (bool is_favourite) throws PropertyError
{
if (this._is_favourite == is_favourite)
{
if (this._is_favourite == value)
return;
return;
}
if (this._is_constructed)
((Tpf.PersonaStore) this.store).change_is_favourite (this, value);
this._is_favourite = value;
if (this._is_constructed)
{
yield ((Tpf.PersonaStore) this.store).change_is_favourite (this,
is_favourite);
}
this._is_favourite = is_favourite;
this.notify_property ("is-favourite");
}
/**
......
......@@ -332,23 +332,29 @@ public class Trf.Persona : Folks.Persona,
/**
* Whether this contact is a user-defined favourite.
*/
[CCode (notify = false)]
public bool is_favourite
{
get { return this._is_favourite; }
set
{
if (this._is_favourite == value)
return;
/* Note:
* this property will be set (and notified)
* once we receive a notification event from Tracker
*/
((Trf.PersonaStore) this.store)._set_is_favourite (this, value);
}
set { this.change_is_favourite.begin (value); }
}
/**
* {@inheritDoc}
*
* @since UNRELEASED
*/
public async void change_is_favourite (bool is_favourite) throws PropertyError
{
if (this._is_favourite == is_favourite)
{
return;
}
yield ((Trf.PersonaStore) this.store)._set_is_favourite (this,
is_favourite);
}
private HashSet<string> _local_ids;
private Set<string> _local_ids_ro;
......@@ -1259,8 +1265,7 @@ public class Trf.Persona : Folks.Persona,
private void _update_favourite ()
{
var favourite = this._cursor.get_string (Trf.Fields.FAVOURITE).dup ();
this._is_favourite = false;
var is_favourite = false;
if (favourite != null)
{
......@@ -1270,10 +1275,16 @@ public class Trf.Persona : Folks.Persona,
{
if (int.parse (tag) == favorite_tracker_id)
{
this._is_favourite = true;
is_favourite = true;
}
}
}
if (is_favourite != this._is_favourite)
{
this._is_favourite = is_favourite;
this.notify_property ("is-favourite");
}
}
/**
......
/*
* 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
......@@ -30,4 +31,24 @@ public interface Folks.FavouriteDetails : Object
* Whether this contact is a user-defined favourite.
*/
public abstract bool is_favourite { get; set; }
/**
* Change whether the contact is a user-defined favourite.
*
* It's preferred to call this rather than setting
* {@link FavouriteDetails.is_favourite} directly, as this method gives error
* notification and will only return once the favouriteness has been written
* to the relevant backing store (or the operation's failed).
*
* @param is_favourite `true` if the contact is a favourite; `false` otherwise
* @throws PropertyError if setting the favouriteness failed
* @since UNRELEASED
*/
public virtual async void change_is_favourite (bool is_favourite)
throws PropertyError
{
/* Default implementation. */
throw new PropertyError.NOT_WRITEABLE (
_("Favourite status is not writeable on this contact."));
}
}
......@@ -492,31 +492,70 @@ public class Folks.Individual : Object,
* This property is `true` if any of this Individual's {@link Persona}s are
* favourites).
*/
[CCode (notify = false)]
public bool is_favourite
{
get { return this._is_favourite; }
set { this.change_is_favourite.begin (value); }
}
set
/**
* {@inheritDoc}
*
* @since UNRELEASED
*/
public async void change_is_favourite (bool is_favourite) throws PropertyError
{
if (this._is_favourite == is_favourite)
{
if (this._is_favourite == value)
return;
return;
}
debug ("Setting '%s' favourite status to %s", this.id,
value ? "TRUE" : "FALSE");
debug ("Setting '%s' favourite status to %s", this.id,
is_favourite ? "TRUE" : "FALSE");
this._is_favourite = value;
foreach (var p in this._persona_set)
PropertyError? persona_error = null;
var is_favourite_changed = false;
/* Try to write it to only the Personas which have "is-favourite" as a
* writeable property.
*
* NOTE: We don't check whether the persona's store is writeable, as we
* want is-favourite status to propagate to all stores, if possible. This
* is one property which is harmless to propagate. */
foreach (var p in this._persona_set)
{
var a = p as FavouriteDetails;
if (a != null && "is-favourite" in p.writeable_properties)
{
if (p is FavouriteDetails)
try
{
SignalHandler.block_by_func (p,
(void*) this._notify_is_favourite_cb, this);
((FavouriteDetails) p).is_favourite = value;
SignalHandler.unblock_by_func (p,
(void*) this._notify_is_favourite_cb, this);
yield a.change_is_favourite (is_favourite);
debug (" written to persona '%s'", p.uid);
is_favourite_changed = true;
}
catch (PropertyError e)
{
/* Store the first error so we can throw it if setting the
* property fails on every other persona. */
if (persona_error == null)
{
persona_error = e;
}
}
}
}
/* Failure? */
if (is_favourite_changed == false)
{
assert (persona_error != null);
throw persona_error;
}
/* Update our copy of the property. */
this._is_favourite = is_favourite;
this.notify_property ("is-favourite");
}
/**
......
......@@ -12,6 +12,7 @@ folks/avatar-details.vala
folks/backend-store.vala
folks/birthday-details.vala
folks/email-details.vala
folks/favourite-details.vala
folks/im-details.vala
folks/individual-aggregator.vala
folks/postal-address-details.vala
......
......@@ -11,6 +11,7 @@ folks/avatar-details.c
folks/backend-store.c
folks/birthday-details.c
folks/email-details.c
folks/favourite-details.c
folks/im-details.c
folks/individual-aggregator.c
folks/postal-address-details.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