/* * 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; } }