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

core: Add ImDetails.change_im_addresses()

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

Helps: bgo#657510
parent ef3d3b73
......@@ -1118,7 +1118,7 @@ public class Edsf.PersonaStore : Folks.PersonaStore
}
internal async void _set_im_fds (Edsf.Persona persona,
MultiMap<string, ImFieldDetails> im_fds)
MultiMap<string, ImFieldDetails> im_fds) throws PropertyError
{
if (Utils.multi_map_str_afd_equal (persona.im_addresses, im_fds))
return;
......@@ -1129,9 +1129,9 @@ public class Edsf.PersonaStore : Folks.PersonaStore
yield this._set_contact_im_fds (contact, im_fds);
yield this._addressbook.modify_contact (contact, null);
}
catch (GLib.Error error)
catch (GLib.Error e)
{
GLib.warning ("Can't update IM addresses: %s\n", error.message);
throw this.e_client_error_to_property_error ("im-addresses", e);
}
}
......
......@@ -380,10 +380,18 @@ public class Edsf.Persona : Folks.Persona,
public MultiMap<string, ImFieldDetails> im_addresses
{
get { return this._im_addresses; }
set
{
((Edsf.PersonaStore) this.store)._set_im_fds (this, value);
}
set { this.change_im_addresses.begin (value); }
}
/**
* {@inheritDoc}
*
* @since UNRELEASED
*/
public async void change_im_addresses (
MultiMap<string, ImFieldDetails> im_addresses) throws PropertyError
{
yield ((Edsf.PersonaStore) this.store)._set_im_fds (this, im_addresses);
}
private HashSet<string> _groups;
......
......@@ -103,72 +103,83 @@ public class Folks.Backends.Kf.Persona : Folks.Persona,
/**
* {@inheritDoc}
*/
[CCode (notify = false)]
public MultiMap<string, ImFieldDetails> im_addresses
{
get
{ return this._im_addresses; }
get { return this._im_addresses; }
set { this.change_im_addresses.begin (value); }
}
set
/**
* {@inheritDoc}
*
* @since UNRELEASED
*/
public async void change_im_addresses (
MultiMap<string, ImFieldDetails> im_addresses) throws PropertyError
{
/* Remove the current IM addresses from the key file */
foreach (var protocol1 in this._im_addresses.get_keys ())
{
/* Remove the current IM addresses from the key file */
foreach (var protocol in this._im_addresses.get_keys ())
try
{
try
{
this._key_file.remove_key (this.display_id, protocol);
}
catch (KeyFileError e)
{
/* Ignore the error, since it's just a group or key not found
* error. */
}
this._key_file.remove_key (this.display_id, protocol1);
}
catch (KeyFileError e1)
{
/* Ignore the error, since it's just a group or key not found
* error. */
}
}
/* Add the new IM addresses to the key file and build a normalised
* table of them to set as the new property value */
var im_addresses = new HashMultiMap<string, ImFieldDetails> (
null, null,
(GLib.HashFunc) ImFieldDetails.hash,
(GLib.EqualFunc) ImFieldDetails.equal);
/* Add the new IM addresses to the key file and build a normalised
* table of them to set as the new property value */
var new_im_addresses = new HashMultiMap<string, ImFieldDetails> (
null, null,
(GLib.HashFunc) ImFieldDetails.hash,
(GLib.EqualFunc) ImFieldDetails.equal);
foreach (var protocol in value.get_keys ())
{
var addresses = value.get (protocol);
var normalised_addresses = new HashSet<string> ();
foreach (var protocol2 in im_addresses.get_keys ())
{
var addresses = im_addresses.get (protocol2);
var normalised_addresses = new HashSet<string> ();
foreach (var im_fd in addresses)
foreach (var im_fd in addresses)
{
string normalised_address;
try
{
string normalised_address;
try
{
normalised_address = ImDetails.normalise_im_address (
im_fd.value, protocol);
}
catch (ImDetailsError e)
{
/* Somehow an error has crept into the user's
* relationships.ini. Warn of it and ignore the IM
* address. */
warning (e.message);
continue;
}
normalised_addresses.add (normalised_address);
var new_im_fd = new ImFieldDetails (normalised_address);
im_addresses.set (protocol, new_im_fd);
normalised_address = ImDetails.normalise_im_address (
im_fd.value, protocol2);
}
catch (ImDetailsError e2)
{
throw new PropertyError.INVALID_VALUE (
/* Translators: this is an error message for if the user
* provides an invalid IM address. The first parameter is
* an IM address (e.g. “foo@jabber.org”), the second is
* the name of a protocol (e.g. “jabber”) and the third is
* an error message. */
_("Invalid IM address ‘%s’ for protocol ‘%s’: %s"),
im_fd.value, protocol2, e2.message);
}
string[] addrs = (string[]) normalised_addresses.to_array ();
addrs.length = normalised_addresses.size;
this._key_file.set_string_list (this.display_id, protocol, addrs);
normalised_addresses.add (normalised_address);
var new_im_fd = new ImFieldDetails (normalised_address);
new_im_addresses.set (protocol2, new_im_fd);
}
this._im_addresses = im_addresses;
string[] addrs = (string[]) normalised_addresses.to_array ();
addrs.length = normalised_addresses.size;
/* Get the PersonaStore to save the key file */
((Kf.PersonaStore) this.store).save_key_file.begin ();
this._key_file.set_string_list (this.display_id, protocol2, addrs);
}
/* Get the PersonaStore to save the key file */
yield ((Kf.PersonaStore) this.store).save_key_file ();
this._im_addresses = new_im_addresses;
this.notify_property ("im-addresses");
}
/**
......
......@@ -136,10 +136,11 @@ public class Swf.Persona : Folks.Persona,
/**
* {@inheritDoc}
*/
[CCode (notify = false)]
public MultiMap<string, ImFieldDetails> im_addresses
{
get { return this._im_addresses; }
private set {}
set { this.change_im_addresses.begin (value); }
}
/**
......
......@@ -176,10 +176,11 @@ public class Tpf.Persona : Folks.Persona,
*
* See {@link Folks.ImDetails.im_addresses}.
*/
[CCode (notify = false)]
public MultiMap<string, ImFieldDetails> im_addresses
{
get { return this._im_addresses; }
private set {}
set { this.change_im_addresses.begin (value); }
}
/**
......
......@@ -284,14 +284,23 @@ public class Trf.Persona : Folks.Persona,
/**
* {@inheritDoc}
*/
[CCode (notify = false)]
public MultiMap<string, ImFieldDetails> im_addresses
{
get { return this._im_addresses; }
public set
{
((Trf.PersonaStore) this.store)._set_im_addresses (this,
value);
}
set { this.change_im_addresses.begin (value); }
}
/**
* {@inheritDoc}
*
* @since UNRELEASED
*/
public async void change_im_addresses (
MultiMap<string, ImFieldDetails> im_addresses) throws PropertyError
{
yield ((Trf.PersonaStore) this.store)._set_im_addresses (this,
im_addresses);
}
/**
......
/*
* 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
......@@ -109,6 +110,26 @@ public interface Folks.ImDetails : Object
get; set;
}
/**
* Change the contact's set of IM addresses.
*
* It's preferred to call this rather than setting
* {@link ImDetails.im_addresses} directly, as this method gives error
* notification and will only return once the IM addresses have been written
* to the relevant backing store (or the operation's failed).
*
* @param im_addresses the new map of protocols to IM addresses
* @throws PropertyError if setting the IM addresses failed
* @since UNRELEASED
*/
public virtual async void change_im_addresses (
MultiMap<string, ImFieldDetails> im_addresses) throws PropertyError
{
/* Default implementation. */
throw new PropertyError.NOT_WRITEABLE (
_("IM addresses are not writeable on this contact."));
}
/**
* Normalise an IM address so that it's suitable for string comparison.
*
......
......@@ -517,10 +517,11 @@ public class Folks.Individual : Object,
/**
* {@inheritDoc}
*/
[CCode (notify = false)]
public MultiMap<string, ImFieldDetails> im_addresses
{
get { return this._im_addresses; }
private set {}
set { this.change_im_addresses.begin (value); } /* not writeable */
}
/**
......
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