/*
* Copyright (C) 2010 Collabora Ltd.
*
* 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
* the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see .
*
* Authors:
* Philip Withnall
*/
using Folks;
using Gee;
using GLib;
private class Folks.Inspect.Utils
{
/* The current indentation level, in spaces */
private static uint indentation = 0;
private static string indentation_string = "";
public static void init ()
{
Utils.indentation_string = "";
/* Register some general transformation functions */
Value.register_transform_func (typeof (Object), typeof (string),
Utils.transform_object_to_string);
Value.register_transform_func (typeof (Folks.PersonaStore),
typeof (string), Utils.transform_persona_store_to_string);
Value.register_transform_func (typeof (string[]), typeof (string),
Utils.transform_string_array_to_string);
}
private static void transform_object_to_string (Value src,
out Value dest)
{
/* FIXME: works around bgo#638363 */
Value dest_tmp = Value (typeof (string));
dest_tmp.take_string ("%p".printf (src.get_object ()));
dest = dest_tmp;
}
private static void transform_persona_store_to_string (Value src,
out Value dest)
{
/* FIXME: works around bgo#638363 */
Value dest_tmp = Value (typeof (string));
Folks.PersonaStore store = (Folks.PersonaStore) src.get_object ();
dest_tmp.take_string ("%p: %s, %s (%s)".printf (store, store.type_id,
store.id, store.display_name));
dest = dest_tmp;
}
private static void transform_string_array_to_string (Value src,
out Value dest)
{
/* FIXME: works around bgo#638363 */
Value dest_tmp = Value (typeof (string));
unowned string[] array = (string[]) src.get_boxed ();
string output = "{ ";
bool first = true;
/* FIXME: Work around bgo#656467 by using for() instead of foreach() */
for (uint i = 0; array[i] != null; i++)
{
var element = array[i];
if (first == false)
output += ", ";
output += "'%s'".printf (element);
first = false;
}
output += " }";
dest_tmp.take_string (output);
dest = dest_tmp;
}
public static void indent ()
{
/* We indent in increments of two spaces */
Utils.indentation += 2;
Utils.indentation_string = string.nfill (Utils.indentation, ' ');
}
public static void unindent ()
{
Utils.indentation -= 2;
Utils.indentation_string = string.nfill (Utils.indentation, ' ');
}
[PrintfFormat ()]
public static void print_line (string format, ...)
{
/* FIXME: store the va_list temporarily to work around bgo#638308 */
var valist = va_list ();
string output = format.vprintf (valist);
stdout.printf ("%s%s\n", Utils.indentation_string, output);
}
public static void print_individual (Individual individual,
bool show_personas)
{
Utils.print_line ("Individual '%s' with %u personas:",
individual.id, individual.personas.size);
/* List the Individual's properties */
unowned ParamSpec[] properties =
individual.get_class ().list_properties ();
Utils.indent ();
foreach (unowned ParamSpec pspec in properties)
{
Value prop_value;
string output_string;
/* Ignore the personas property if we're printing the personas out */
if (show_personas == true && pspec.get_name () == "personas")
continue;
prop_value = Value (pspec.value_type);
individual.get_property (pspec.get_name (), ref prop_value);
output_string = Utils.property_to_string (individual.get_type (),
pspec.get_name (), prop_value);
Utils.print_line ("%-20s %s", pspec.get_nick (), output_string);
}
if (show_personas == true)
{
Utils.print_line ("");
Utils.print_line ("Personas:");
Utils.indent ();
foreach (Persona persona in individual.personas)
Utils.print_persona (persona);
Utils.unindent ();
}
Utils.unindent ();
}
public static void print_persona (Persona persona)
{
Utils.print_line ("Persona '%s':", persona.uid);
/* List the Persona's properties */
unowned ParamSpec[] properties =
persona.get_class ().list_properties ();
Utils.indent ();
foreach (unowned ParamSpec pspec in properties)
{
Value prop_value;
string output_string;
prop_value = Value (pspec.value_type);
persona.get_property (pspec.get_name (), ref prop_value);
output_string = Utils.property_to_string (persona.get_type (),
pspec.get_name (), prop_value);
Utils.print_line ("%-20s %s", pspec.get_nick (), output_string);
}
Utils.unindent ();
}
public static void print_persona_store (PersonaStore store,
bool show_personas)
{
if (store.is_prepared == false)
{
Utils.print_line ("Persona store '%s':", store.id);
Utils.indent ();
Utils.print_line ("Not prepared.");
Utils.unindent ();
return;
}
Utils.print_line ("Persona store '%s' with %u personas:",
store.id, store.personas.size);
/* List the store's properties */
unowned ParamSpec[] properties =
store.get_class ().list_properties ();
Utils.indent ();
foreach (unowned ParamSpec pspec in properties)
{
Value prop_value;
string output_string;
/* Ignore the personas property if we're printing the personas out */
if (show_personas == true && pspec.get_name () == "personas")
continue;
prop_value = Value (pspec.value_type);
store.get_property (pspec.get_name (), ref prop_value);
output_string = Utils.property_to_string (store.get_type (),
pspec.get_name (), prop_value);
Utils.print_line ("%-20s %s", pspec.get_nick (), output_string);
}
if (show_personas == true)
{
Utils.print_line ("");
Utils.print_line ("Personas:");
Utils.indent ();
foreach (var persona in store.personas.values)
{
Utils.print_persona (persona);
}
Utils.unindent ();
}
Utils.unindent ();
}
private static string property_to_string (Type object_type,
string prop_name,
Value prop_value)
{
string output_string;
/* Overrides for various known properties */
if (object_type.is_a (typeof (Individual)) && prop_name == "personas")
{
Set personas = (Set) prop_value.get_object ();
return "List of %u personas".printf (personas.size);
}
else if (object_type.is_a (typeof (PersonaStore)) &&
prop_name == "personas")
{
Map personas =
(Map) prop_value.get_object ();
return "Set of %u personas".printf (personas.size);
}
else if (prop_name == "groups" ||
prop_name == "local-ids")
{
Set groups = (Set) prop_value.get_object ();
output_string = "{ ";
bool first = true;
foreach (var group in groups)
{
if (first == false)
output_string += ", ";
output_string += "'%s'".printf (group);
first = false;
}
output_string += " }";
return output_string;
}
else if (prop_name == "avatar")
{
string ret = null;
LoadableIcon? avatar = (LoadableIcon) prop_value.get_object ();
if (avatar != null &&
avatar is FileIcon && ((FileIcon) avatar).get_file () != null)
{
ret = "%p (file: %s)".printf (avatar,
((FileIcon) avatar).get_file ().get_uri ());
}
else if (avatar != null)
{
ret = "%p".printf (avatar);
}
return ret;
}
else if (prop_name == "im-addresses" ||
prop_name == "web-service-addresses")
{
var prop_list =
(MultiMap>)
prop_value.get_object ();
output_string = "{ ";
bool first = true;
foreach (var k in prop_list.get_keys ())
{
if (first == false)
output_string += ", ";
output_string += "'%s' : { ".printf (k);
first = false;
var v = prop_list.get (k);
bool _first = true;
foreach (var a in v)
{
if (_first == false)
output_string += ", ";
output_string += "'%s'".printf (a.value);
_first = false;
}
output_string += " }";
}
output_string += " }";
return output_string;
}
else if (prop_name == "email-addresses" ||
prop_name == "phone-numbers" ||
prop_name == "urls")
{
output_string = "{ ";
bool first = true;
var prop_list =
(Set>) prop_value.get_object ();
foreach (var p in prop_list)
{
if (!first)
{
output_string += ", ";
}
output_string += p.value;
first = false;
}
output_string += " }";
return output_string;
}
else if (prop_name == "birthday")
{
unowned DateTime dobj = (DateTime) prop_value.get_boxed ();
if (dobj != null)
return dobj.to_string ();
else
return "";
}
else if (prop_name == "postal-addresses")
{
output_string = "{ ";
bool first = true;
var prop_list =
(Set) prop_value.get_object ();
foreach (var p in prop_list)
{
if (!first)
{
output_string += ". ";
}
output_string += p.value.to_string ();
first = false;
}
output_string += " }";
return output_string;
}
else if (prop_name == "notes")
{
Set notes =
prop_value.get_object () as Set;
output_string = "{ ";
bool first = true;
foreach (var note in notes)
{
if (!first)
{
output_string += ", ";
}
output_string += note.uid;
first = false;
}
output_string += " }";
return output_string;
}
else if (prop_name == "roles")
{
var roles = (Set) prop_value.get_object ();
output_string = "{ ";
bool first = true;
foreach (var role in roles)
{
if (!first)
{
output_string += ", ";
}
output_string += role.value.to_string ();
first = false;
}
output_string += " }";
return output_string;
}
else if (prop_name == "structured-name")
{
unowned StructuredName sn = (StructuredName) prop_value.get_object ();
string ret = null;
if (sn != null)
ret = sn.to_string ();
return ret;
}
return Utils.transform_value_to_string (prop_value);
}
public static string transform_value_to_string (Value prop_value)
{
if (Value.type_transformable (prop_value.type (), typeof (string)))
{
/* Convert to a string value */
Value string_value = Value (typeof (string));
prop_value.transform (ref string_value);
return string_value.get_string ();
}
else
{
/* Can't convert the property value to a string */
return "Can't convert from type '%s' to '%s'".printf (
prop_value.type ().name (), typeof (string).name ());
}
}
/* FIXME: This can't be in the command_completion_cb() function because Vala
* doesn't allow static local variables. Erk. */
private static MapIterator? command_name_iter = null;
/* Complete a command name, starting with @word. */
public static string? command_name_completion_cb (string word,
int state)
{
/* Initialise state. Whoever wrote the readline API should be shot. */
if (state == 0)
Utils.command_name_iter = main_client.commands.map_iterator ();
while (Utils.command_name_iter.next () == true)
{
string command_name = Utils.command_name_iter.get_key ();
if (command_name.has_prefix (word))
return command_name;
}
/* Clean up */
Utils.command_name_iter = null;
return null;
}
/* FIXME: This can't be in the individual_id_completion_cb() function because
* Vala doesn't allow static local variables. Erk. */
private static MapIterator? individual_id_iter = null;
/* Complete an individual's ID, starting with @word. */
public static string? individual_id_completion_cb (string word,
int state)
{
/* Initialise state. Whoever wrote the readline API should be shot. */
if (state == 0)
{
Utils.individual_id_iter =
main_client.aggregator.individuals.map_iterator ();
}
while (Utils.individual_id_iter.next () == true)
{
var id = Utils.individual_id_iter.get_key ();
if (id.has_prefix (word))
return id;
}
/* Clean up */
Utils.individual_id_iter = null;
return null;
}
/* FIXME: This can't be in the individual_id_completion_cb() function because
* Vala doesn't allow static local variables. Erk. */
private static Iterator? persona_uid_iter = null;
/* Complete an individual's ID, starting with @word. */
public static string? persona_uid_completion_cb (string word,
int state)
{
/* Initialise state. Whoever wrote the readline API should be shot. */
if (state == 0)
{
Utils.individual_id_iter =
main_client.aggregator.individuals.map_iterator ();
Utils.persona_uid_iter = null;
}
while (Utils.persona_uid_iter != null ||
Utils.individual_id_iter.next () == true)
{
var individual = Utils.individual_id_iter.get_value ();
if (Utils.persona_uid_iter == null)
{
assert (individual != null);
Utils.persona_uid_iter = individual.personas.iterator ();
}
while (Utils.persona_uid_iter.next ())
{
var persona = Utils.persona_uid_iter.get ();
if (persona.uid.has_prefix (word))
return persona.uid;
}
/* Clean up */
Utils.persona_uid_iter = null;
}
/* Clean up */
Utils.individual_id_iter = null;
return null;
}
/* FIXME: This can't be in the backend_name_completion_cb() function because
* Vala doesn't allow static local variables. Erk. */
private static Iterator? backend_name_iter = null;
/* Complete an individual's ID, starting with @word. */
public static string? backend_name_completion_cb (string word,
int state)
{
/* Initialise state. Whoever wrote the readline API should be shot. */
if (state == 0)
{
Utils.backend_name_iter =
main_client.backend_store.list_backends ().iterator ();
}
while (Utils.backend_name_iter.next () == true)
{
Backend backend = Utils.backend_name_iter.get ();
if (backend.name.has_prefix (word))
return backend.name;
}
/* Clean up */
Utils.backend_name_iter = null;
return null;
}
/* FIXME: This can't be in the persona_store_id_completion_cb() function
* because Vala doesn't allow static local variables. Erk. */
private static MapIterator? persona_store_id_iter =
null;
/* Complete a persona store's ID, starting with @word. */
public static string? persona_store_id_completion_cb (string word,
int state)
{
/* Initialise state. Whoever wrote the readline API should be shot. */
if (state == 0)
{
Utils.backend_name_iter =
main_client.backend_store.list_backends ().iterator ();
Utils.persona_store_id_iter = null;
}
while (Utils.persona_store_id_iter != null ||
Utils.backend_name_iter.next () == true)
{
if (Utils.persona_store_id_iter == null)
{
Backend backend = Utils.backend_name_iter.get ();
Utils.persona_store_id_iter =
backend.persona_stores.map_iterator ();
}
while (Utils.persona_store_id_iter.next () == true)
{
var id = Utils.persona_store_id_iter.get_key ();
if (id.has_prefix (word))
return id;
}
/* Clean up */
Utils.persona_store_id_iter = null;
}
/* Clean up */
Utils.backend_name_iter = null;
return null;
}
}