Logo Search packages:      
Sourcecode: telepathy-inspector version File versions  Download package

ti-page-presence.c

/*
 * Telapathy Inspector - A Telepathy client which exposes Telepathy interfaces.
 *                       Meant to inspect and/or test connection managers.
 * 
 * ti-page-presence.c:
 * A GtkNotebook page exposing org.freedesktop.Telepathy.Connection.Interface.Presence
 * functionality.
 * 
 * Copyright (C) 2006 INdT - Instituto Nokia de Tecnologia
 * Author - Daniel d'Andrada T. de Carvalho <daniel.carvalho@indt.org.br>
 *
 * This program 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 of the License, or
 * (at your option) any later version.
 *
 * This program 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 Library General Public License
 * along with this library; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "ti-page-presence.h"
#include "ti-page-priv.h"
#include "ti-config.h"
#include "ti-constants.h"
#include "ti-dlg-user-status.h"
#include "ti-dlg-handles-list.h"
#include "ti-util.h"
#include "ti-preferences.h"

#include <glade/glade.h>

struct _TIPagePresenceClass {
    TIPageClass parent;
};

G_DEFINE_TYPE (TIPagePresence, ti_page_presence, TI_TYPE_PAGE);

enum {
    TI_COLUMN_PRESENCE_LIST_NAME = 0,
    TI_COLUMN_PRESENCE_LIST_HANDLE,
    TI_COLUMN_PRESENCE_LIST_TIMESTAMP,
    TI_COLUMN_PRESENCE_LIST_STATUS,
    TI_COLUMN_PRESENCE_LIST_N_COLUMNS
};

/* Function prototypes */
void _ti_page_presence_setup_page (TIPage* page, GladeXML* glade_xml);
void _ti_page_presence_restart_page (TIPage* page);
static void _ti_page_presence_refresh_valid_statuses (TIPagePresence* page_presence);
static void _ti_page_presence_build_valid_statuses_treeview (TIPagePresence* page_presence, GladeXML* glade_xml);
static void _ti_page_presence_build_presence_treeview (TIPagePresence* page_presence, GladeXML* glade_xml);
static void _add_valid_status_to_list (gpointer key, gpointer value, gpointer user_data);
static gchar* _get_presence_status_type_string (guint presence_status_type);
static void _ti_page_presence_add_valid_status_opt_params_to_list (TIPagePresence* page_presence, const gchar* status_name, GHashTable* opt_params);
static void _ti_page_presence_show_selected_valid_status_opt_params_list (TIPagePresence* page_presence);
static void _ti_page_presence_show_selected_presence_opt_params_list (TIPagePresence* page_presence);
static void _ti_page_presence_build_valid_status_opt_params_treeview (TIPagePresence* page_presence, GladeXML* glade_xml);
static void _ti_page_presence_build_presence_opt_params_treeview (TIPagePresence* page_presence, GladeXML* glade_xml);
static void _ti_page_presence_presence_update (TIPagePresence* page_presence, GHashTable* presence_update);
static void _ti_page_presence_remove_presence (TIPagePresence* page_presence, guint contact_handle);
static void _ti_page_presence_add_presence (TIPagePresence* page_presence, guint contact_handle, guint timestamp, GHashTable* statuses);
static void _ti_page_presence_add_presence_opt_params_to_list (TIPagePresence* page_presence,
                                                               const gchar* handle,
                                                               const gchar* status,
                                                               GHashTable* opt_params);
static void _ti_page_presence_request_presence (TIPagePresence* page_presence);
static void _ti_page_presence_clear_presence_list (TIPagePresence* page_presence);
static void _ti_page_presence_add_user_status (TIPagePresence* page_presence);
static void _ti_page_presence_clear_user_status (TIPagePresence* page_presence);
static void _ti_page_presence_remove_user_status (TIPagePresence* page_presence);
static void _ti_page_presence_handle_display_mode_changed (TIPagePresence* page_presence, guint handle_display_mode);

/**
 * Instance private data.
 */
00082 struct _TIPagePresencePrivate {
    TIPreferences* preferences;
    TIHandleMapper* handle_mapper;

    TIConnection* connection;

    TIDlgUserStatus* dlg_user_status;
    TIDlgHandlesList* dlg_handles_list;

    GtkWindow* parent_wnd;

    GtkListStore* valid_statuses_list;
    GtkTreeSelection* valid_statuses_selection;

    GtkTreeView* presence_treeview;
    GtkTreeStore* presence_tree;
    GtkTreeSelection* presence_selection;

    // Maps a valid status' name with its optional parameters (a GtkListStore).
    GHashTable* hashtable_valid_status_opt_params_list;

    // Maps a "handle-status" (e.g. "1010-available") string with its optional parameters (a GtkListStore).
    GHashTable* hashtable_presence_opt_params_list;

    GtkTreeView* treeview_valid_status_opt_params;
    GtkTreeView* treeview_presence_opt_params;
};
typedef struct _TIPagePresencePrivate TIPagePresencePrivate;

#define TI_PAGE_PRESENCE_GET_PRIVATE(object)  (G_TYPE_INSTANCE_GET_PRIVATE ((object), TI_TYPE_PAGE_PRESENCE, TIPagePresencePrivate))

/**
 * Drop all references to other objects.
 */
static void
ti_page_presence_dispose (GObject *object)
{
    TIPagePresence* self = TI_PAGE_PRESENCE (object);
    TIPagePresencePrivate *priv = TI_PAGE_PRESENCE_GET_PRIVATE (self);

    if (priv->preferences != NULL)
    {
        g_signal_handlers_disconnect_by_func(priv->preferences,
                                             G_CALLBACK (_ti_page_presence_handle_display_mode_changed),
                                             self);
        g_object_unref (priv->preferences);
        priv->preferences = NULL;
    }

    TI_OBJ_UNREF (priv->handle_mapper);
    TI_OBJ_UNREF (priv->connection);
    TI_OBJ_UNREF (priv->dlg_user_status);
    TI_OBJ_UNREF (priv->dlg_handles_list);

    if (priv->hashtable_valid_status_opt_params_list != NULL)
    {
        g_hash_table_destroy (priv->hashtable_valid_status_opt_params_list);
        priv->hashtable_valid_status_opt_params_list = NULL;
    }

    if (priv->hashtable_presence_opt_params_list != NULL)
    {
        g_hash_table_destroy (priv->hashtable_presence_opt_params_list);
        priv->hashtable_presence_opt_params_list = NULL;
    }

    G_OBJECT_CLASS (ti_page_presence_parent_class)->dispose (object);
}

/**
 * Class initialization.
 */
static void
ti_page_presence_class_init (TIPagePresenceClass *ti_page_presence_class)
{
      GObjectClass *gobject_class = G_OBJECT_CLASS (ti_page_presence_class);
    TIPageClass* page_class = TI_PAGE_CLASS (ti_page_presence_class);

      /* override base object methods */ 
      gobject_class->dispose = ti_page_presence_dispose;

    page_class->setup_page = _ti_page_presence_setup_page;
    page_class->restart_page = _ti_page_presence_restart_page;
            
      /* Add private */
      g_type_class_add_private (ti_page_presence_class, sizeof (TIPagePresencePrivate));
}

/**
 * Instance initialization.
 */
static void
ti_page_presence_init (TIPagePresence *ti_page_presence)
{
    TIPagePresencePrivate *priv = TI_PAGE_PRESENCE_GET_PRIVATE (ti_page_presence);

    priv->preferences = ti_preferences_new ();
    priv->handle_mapper = NULL;
    priv->connection = NULL;
    priv->dlg_user_status = NULL;
    priv->dlg_handles_list = NULL;
    priv->hashtable_valid_status_opt_params_list = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
    priv->hashtable_presence_opt_params_list = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
}

/**
 * Returns a new instance.
 */
TIPagePresence*
ti_page_presence_new (GtkWindow* parent_wnd, GtkNotebook* parent_notebook, TIConnection* connection, TIHandleMapper* handle_mapper) 
{
    TIPagePresence* page_presence;
    TIPagePresencePrivate *priv;

    g_assert (parent_wnd != NULL);

    page_presence = g_object_new (TI_TYPE_PAGE_PRESENCE, NULL);

    priv = TI_PAGE_PRESENCE_GET_PRIVATE (page_presence);
    priv->parent_wnd = parent_wnd;

    priv->connection = connection;
    g_object_ref (connection);

    priv->handle_mapper = handle_mapper;
    g_object_ref (handle_mapper);

    priv->dlg_handles_list = ti_dlg_handles_list_new (parent_wnd, handle_mapper, "Request Presence");
    g_assert (priv->dlg_handles_list != NULL);

    g_signal_connect_swapped (priv->preferences, "handle-display-mode-changed",
                              G_CALLBACK (_ti_page_presence_handle_display_mode_changed), page_presence);

    _ti_page_new ((TIPage**)&page_presence, parent_notebook, "page-presence.xml");

    return page_presence;
}

/**
 * Setup Page
 */
void
_ti_page_presence_setup_page (TIPage* page, GladeXML* glade_xml)
{
    TIPagePresence* page_presence = TI_PAGE_PRESENCE (page);
    TIPagePresencePrivate *priv = TI_PAGE_PRESENCE_GET_PRIVATE (page_presence);
    GtkWidget* widget = NULL;

    // "Refresh" button in "Valid statuses" frame.
    widget = glade_xml_get_widget (glade_xml, "button_refresh_valid_statuses");
    g_assert (GTK_IS_BUTTON (widget));
    g_signal_connect_swapped (widget, "clicked", G_CALLBACK (_ti_page_presence_refresh_valid_statuses), page_presence);

    // Valid statuses list
    priv->valid_statuses_list = gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN);
    _ti_page_presence_build_valid_statuses_treeview (page_presence, glade_xml);

    // "Add Status" dialog
    priv->dlg_user_status = ti_dlg_user_status_new (priv->parent_wnd, GTK_TREE_MODEL (priv->valid_statuses_list), 0);
    g_assert (priv->dlg_user_status != NULL);

    // Valid status' optional parameters list
    _ti_page_presence_build_valid_status_opt_params_treeview (page_presence, glade_xml);

    // Presence Tree
    priv->presence_tree = gtk_tree_store_new (4,
                                              G_TYPE_STRING, // name
                                              G_TYPE_STRING, // handle
                                              G_TYPE_STRING, // timestamp 
                                              G_TYPE_STRING);// status id
    _ti_page_presence_build_presence_treeview (page_presence, glade_xml);
    g_signal_connect_swapped (priv->connection, "presence-update", G_CALLBACK (_ti_page_presence_presence_update), page_presence);

    // Presence's optional parameters list
    _ti_page_presence_build_presence_opt_params_treeview (page_presence, glade_xml);

    // "Request Presence" button
    widget = glade_xml_get_widget (glade_xml, "button_request_presence");
    g_assert (GTK_IS_BUTTON (widget));
    g_signal_connect_swapped (widget, "clicked", G_CALLBACK (_ti_page_presence_request_presence), page_presence);

    // "Clear Presence List" button
    widget = glade_xml_get_widget (glade_xml, "button_presence_clear");
    g_assert (GTK_IS_BUTTON (widget));
    g_signal_connect_swapped (widget, "clicked", G_CALLBACK (_ti_page_presence_clear_presence_list), page_presence);

    // "Add Status" button
    widget = glade_xml_get_widget (glade_xml, "button_user_status_add");
    g_assert (GTK_IS_BUTTON (widget));
    g_signal_connect_swapped (widget, "clicked", G_CALLBACK (_ti_page_presence_add_user_status), page_presence);

    // "Clear Status" button
    widget = glade_xml_get_widget (glade_xml, "button_user_status_clear");
    g_assert (GTK_IS_BUTTON (widget));
    g_signal_connect_swapped (widget, "clicked", G_CALLBACK (_ti_page_presence_clear_user_status), page_presence);

    // "Remove Status" button
    widget = glade_xml_get_widget (glade_xml, "button_user_status_remove");
    g_assert (GTK_IS_BUTTON (widget));
    g_signal_connect_swapped (widget, "clicked", G_CALLBACK (_ti_page_presence_remove_user_status), page_presence);
}

/**
 * Restart Page
 */
void
_ti_page_presence_restart_page (TIPage* page)
{
    g_assert (page != NULL && TI_IS_PAGE_PRESENCE (page));
    TIPagePresence* page_presence = TI_PAGE_PRESENCE (page);

    _ti_page_presence_refresh_valid_statuses (page_presence);
}

/**
 * Refresh Valid Statuses
 */
static void
_ti_page_presence_refresh_valid_statuses (TIPagePresence* page_presence)
{
    TIPagePresencePrivate* priv = TI_PAGE_PRESENCE_GET_PRIVATE (page_presence);
    GError* error = NULL;
    GHashTable* statuses = NULL;

    // Clean up current data
    gtk_list_store_clear (priv->valid_statuses_list);

    g_hash_table_destroy (priv->hashtable_valid_status_opt_params_list);
    priv->hashtable_valid_status_opt_params_list = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);

    gtk_tree_view_set_model (priv->treeview_valid_status_opt_params, NULL);

    // Fetch new data
    statuses = ti_connection_ipresence_get_statuses (priv->connection, &error);
    if (error != NULL)
    {
        // TODO: Display a message or something.
        goto CLEAN_UP;
    }

    g_hash_table_foreach (statuses, _add_valid_status_to_list, page_presence);

    CLEAN_UP:
    if (error != NULL)
        g_error_free (error);

    if (statuses != NULL)
        g_hash_table_destroy (statuses);
}

/**
 * Build "Valid Statuses" Treeview
 */
static void
_ti_page_presence_build_valid_statuses_treeview (TIPagePresence* page_presence, GladeXML* glade_xml)
{
    TIPagePresencePrivate* priv = TI_PAGE_PRESENCE_GET_PRIVATE (page_presence);
    GtkWidget* treeview;
    GtkCellRenderer* renderer;
    GtkTreeViewColumn* column;

    treeview = glade_xml_get_widget (glade_xml, "treeview_valid_statuses");
    gtk_tree_view_set_model (GTK_TREE_VIEW(treeview), GTK_TREE_MODEL(priv->valid_statuses_list));

    renderer = gtk_cell_renderer_text_new ();
    
    /* Name column */
    column = gtk_tree_view_column_new_with_attributes ("Name",
                                                       renderer,
                                                       "text", 0,
                                                       NULL);
    gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
    
    /* Type column */
    column = gtk_tree_view_column_new_with_attributes ("Type",
                                                       renderer,
                                                       "text", 1,
                                                       NULL);
    gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
    
    /* Self column */
    column = gtk_tree_view_column_new_with_attributes ("Self",
                                                       renderer,
                                                       "text", 2,
                                                       NULL);
    gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
    
    /* Exclusive column */
    column = gtk_tree_view_column_new_with_attributes ("Exclusive",
                                                       renderer,
                                                       "text", 3,
                                                       NULL);
    gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
    
    priv->valid_statuses_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));

    g_signal_connect_swapped (priv->valid_statuses_selection, "changed",
                              G_CALLBACK (_ti_page_presence_show_selected_valid_status_opt_params_list),
                              page_presence);

    gtk_tree_selection_set_mode (priv->valid_statuses_selection, GTK_SELECTION_SINGLE);
}

/**
 * Build Presence Treeview
 */
static void
_ti_page_presence_build_presence_treeview (TIPagePresence* page_presence, GladeXML* glade_xml)
{
    TIPagePresencePrivate* priv = TI_PAGE_PRESENCE_GET_PRIVATE (page_presence);
    GtkCellRenderer* renderer;
    GtkTreeViewColumn* column;

    priv->presence_treeview = GTK_TREE_VIEW (glade_xml_get_widget (glade_xml, "treeview_presence"));
    g_assert (priv->presence_treeview != NULL);

    gtk_tree_view_set_model (priv->presence_treeview, GTK_TREE_MODEL (priv->presence_tree));

    renderer = gtk_cell_renderer_text_new ();

    if (ti_preferences_get_handle_display_mode (priv->preferences) ==
        TI_PREFERENCES_HANDLE_DISPLAY_HANDLE)
    {
        /* Handle column */
        column = gtk_tree_view_column_new_with_attributes ("Handle",
                                                           renderer,
                                                           "text", TI_COLUMN_PRESENCE_LIST_HANDLE,
                                                           NULL);
        gtk_tree_view_append_column (priv->presence_treeview, column);
    }
    else
    {
        /* Name column */
        column = gtk_tree_view_column_new_with_attributes ("Name",
                                                           renderer,
                                                           "text", TI_COLUMN_PRESENCE_LIST_NAME,
                                                           NULL);
        gtk_tree_view_append_column (priv->presence_treeview, column);
    }

    /* Timestamp column */
    column = gtk_tree_view_column_new_with_attributes ("Timestamp",
                                                       renderer,
                                                       "text", TI_COLUMN_PRESENCE_LIST_TIMESTAMP,
                                                       NULL);
    gtk_tree_view_append_column (priv->presence_treeview, column);

    /* ID column */
    column = gtk_tree_view_column_new_with_attributes ("Status Id",
                                                       renderer,
                                                       "text", TI_COLUMN_PRESENCE_LIST_STATUS,
                                                       NULL);
    gtk_tree_view_append_column (priv->presence_treeview, column);    

    priv->presence_selection = gtk_tree_view_get_selection (priv->presence_treeview);

    g_signal_connect_swapped (priv->presence_selection, "changed",
                              G_CALLBACK (_ti_page_presence_show_selected_presence_opt_params_list),
                              page_presence);

    gtk_tree_selection_set_mode (priv->presence_selection, GTK_SELECTION_SINGLE);
}

/**
 * Build Valid Status Optional Parameters TreeView
 */
static void
_ti_page_presence_build_valid_status_opt_params_treeview (TIPagePresence* page_presence, GladeXML* glade_xml)
{
    TIPagePresencePrivate* priv = TI_PAGE_PRESENCE_GET_PRIVATE (page_presence);
    GtkCellRenderer* renderer;
    GtkTreeViewColumn* column;
    GtkTreeSelection* tree_selection;

    priv->treeview_valid_status_opt_params = GTK_TREE_VIEW (glade_xml_get_widget (glade_xml, "treeview_valid_statuses_optional_arguments"));
    g_assert (priv->treeview_valid_status_opt_params != NULL);
    g_assert (GTK_IS_TREE_VIEW (priv->treeview_valid_status_opt_params));

    renderer = gtk_cell_renderer_text_new ();
    
    /* Name column */
    column = gtk_tree_view_column_new_with_attributes ("Name",
                                                       renderer,
                                                       "text", 0,
                                                       NULL);
    gtk_tree_view_append_column (GTK_TREE_VIEW (priv->treeview_valid_status_opt_params), column);
    
    /* Type column */
    column = gtk_tree_view_column_new_with_attributes ("Type",
                                                       renderer,
                                                       "text", 1,
                                                       NULL);
    gtk_tree_view_append_column (GTK_TREE_VIEW (priv->treeview_valid_status_opt_params), column);

    tree_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview_valid_status_opt_params));
    gtk_tree_selection_set_mode (tree_selection, GTK_SELECTION_NONE);
}

/**
 * Build Presence's Optional Parameters TreeView
 */
static void
_ti_page_presence_build_presence_opt_params_treeview (TIPagePresence* page_presence, GladeXML* glade_xml)
{
    TIPagePresencePrivate* priv = TI_PAGE_PRESENCE_GET_PRIVATE (page_presence);
    GtkCellRenderer* renderer;
    GtkTreeViewColumn* column;
    GtkTreeSelection* tree_selection;

    priv->treeview_presence_opt_params = GTK_TREE_VIEW (glade_xml_get_widget (glade_xml, "treeview_presence_optional_arguments"));
    g_assert (priv->treeview_presence_opt_params != NULL);
    g_assert (GTK_IS_TREE_VIEW (priv->treeview_presence_opt_params));

    renderer = gtk_cell_renderer_text_new ();
    
    /* Name column */
    column = gtk_tree_view_column_new_with_attributes ("Name",
                                                       renderer,
                                                       "text", 0,
                                                       NULL);
    gtk_tree_view_append_column (GTK_TREE_VIEW (priv->treeview_presence_opt_params), column);
    
    /* Type column */
    column = gtk_tree_view_column_new_with_attributes ("Value",
                                                       renderer,
                                                       "text", 1,
                                                       NULL);
    gtk_tree_view_append_column (GTK_TREE_VIEW (priv->treeview_presence_opt_params), column);

    tree_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->treeview_valid_status_opt_params));
    gtk_tree_selection_set_mode (tree_selection, GTK_SELECTION_NONE);
}

/**
 * Add Valid Status to List - Helper Function, called by _ti_page_presence_refresh_valid_statuses()
 */
static void
_add_valid_status_to_list (gpointer key, gpointer value, gpointer user_data)
{
    g_assert (user_data != NULL && TI_IS_PAGE_PRESENCE (user_data));
    TIPagePresence* page_presence = TI_PAGE_PRESENCE (user_data);
    TIPagePresencePrivate* priv = TI_PAGE_PRESENCE_GET_PRIVATE (page_presence);
    const gchar* status_name = (gchar*) key;
    GValueArray* status_info = (GValueArray*) value;
    GtkTreeIter iter;
    gchar* type_str = NULL;
    gboolean self;
    gboolean exclusive;
    GValue* gvalue = NULL;
    GHashTable* opt_params = NULL;
    
    gvalue = g_value_array_get_nth (status_info, 0);
    type_str = _get_presence_status_type_string (g_value_get_uint (gvalue));

    gvalue = g_value_array_get_nth (status_info, 1);
    self = g_value_get_boolean (gvalue);

    gvalue = g_value_array_get_nth (status_info, 2);
    exclusive = g_value_get_boolean (gvalue);

    gtk_list_store_append (priv->valid_statuses_list, &iter);
    gtk_list_store_set (priv->valid_statuses_list, &iter,
                        0, status_name,
                        1, type_str,
                        2, self,
                        3, exclusive,
                        -1);

    gvalue = g_value_array_get_nth (status_info, 3);
    opt_params = (GHashTable*) g_value_get_boxed (gvalue);

    _ti_page_presence_add_valid_status_opt_params_to_list (page_presence, status_name, opt_params);

    g_free (type_str);
}

/**
 * Get Presence Status Type String - Helper Function
 * 
 * @return Presence status type string representation. Must be freed after use.
 */
static gchar*
_get_presence_status_type_string (guint presence_status_type)
{
    switch (presence_status_type)
    {
        case TI_CONNECTION_PRESENCE_TYPE_OFFLINE:
            return g_strdup_printf ("%u - Offline", presence_status_type);

        case TI_CONNECTION_PRESENCE_TYPE_AVAILABLE:
            return g_strdup_printf ("%u - Available", presence_status_type);

        case TI_CONNECTION_PRESENCE_TYPE_AWAY:
            return g_strdup_printf ("%u - Away", presence_status_type);

        case TI_CONNECTION_PRESENCE_TYPE_EXTENDED_AWAY:
            return g_strdup_printf ("%u - Ext. Away", presence_status_type);

        case TI_CONNECTION_PRESENCE_TYPE_HIDDEN:
            return g_strdup_printf ("%u - Hidden", presence_status_type);

        default:
            return g_strdup_printf ("%u - Invalid", presence_status_type);
    }
}

/**
 * Add Valid Status Optional Parameters to List
 */
static void
_ti_page_presence_add_valid_status_opt_params_to_list (TIPagePresence* page_presence, const gchar* status_name, GHashTable* opt_params)
{
    TIPagePresencePrivate* priv = TI_PAGE_PRESENCE_GET_PRIVATE (page_presence);
    GtkListStore* opt_params_list = NULL;
    GArray* opt_params_array = NULL;
    guint i;
    TIHashEntry hash_entry;
    const gchar* param_name;
    const gchar* param_type;
    GtkTreeIter iter;

    opt_params_list = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
    g_hash_table_insert (priv->hashtable_valid_status_opt_params_list, g_strdup (status_name), opt_params_list);
    g_object_ref (opt_params_list);

    opt_params_array = ti_hash_table_to_array (opt_params);

    for (i = 0; i < opt_params_array->len; i++)
    {
        hash_entry = g_array_index (opt_params_array, TIHashEntry, i);

        param_name = (gchar*) hash_entry.key;
        param_type = (gchar*) hash_entry.value;

        gtk_list_store_append (opt_params_list, &iter);
        gtk_list_store_set (opt_params_list, &iter,
                            0, param_name,
                            1, param_type,
                            -1);
    }

    // Clean up
    g_array_free (opt_params_array, TRUE);
}

/**
 * Show Selected Valid Status Optional Parameters' List
 *
 * Shows the optional parameters' list for the selected valid status definition.
 * What a huge function name...
 */
static void
_ti_page_presence_show_selected_valid_status_opt_params_list (TIPagePresence* page_presence)
{
    TIPagePresencePrivate* priv = TI_PAGE_PRESENCE_GET_PRIVATE (page_presence);
    gboolean has_selection;
    GtkTreeIter iter;
    GtkTreeModel* tree_model = NULL;
    gchar* status_name = NULL;
    GtkListStore* opt_params_list = NULL;

    has_selection = gtk_tree_selection_get_selected (priv->valid_statuses_selection, &tree_model, &iter);

    if (has_selection)
    {
        gtk_tree_model_get (tree_model, &iter,
                            0, &status_name,
                            -1);

        opt_params_list = (GtkListStore*) g_hash_table_lookup (priv->hashtable_valid_status_opt_params_list, status_name);

        gtk_tree_view_set_model (GTK_TREE_VIEW(priv->treeview_valid_status_opt_params), GTK_TREE_MODEL(opt_params_list));
    }
    else
    {
        gtk_tree_view_set_model (GTK_TREE_VIEW(priv->treeview_valid_status_opt_params), NULL);
    }

    g_free (status_name);
}

/**
 * Show Selected Presence Optional Parameters' List
 *
 * Shows the optional parameters' list for the selected contact presence.
 * What a huge function name...
 */
static void
_ti_page_presence_show_selected_presence_opt_params_list (TIPagePresence* page_presence)
{
    TIPagePresencePrivate* priv = TI_PAGE_PRESENCE_GET_PRIVATE (page_presence);
    gboolean has_selection;
    GtkTreeIter iter;
    GtkTreeModel* tree_model = NULL;
    gchar* handle = NULL;
    gchar* status = NULL;
    gchar* hash_key;
    GtkListStore* opt_params_list = NULL;
    GtkTreeIter parent_iter;
    gboolean is_child;

    has_selection = gtk_tree_selection_get_selected (priv->presence_selection, &tree_model, &iter);
    if (!has_selection)
    {
        gtk_tree_view_set_model (GTK_TREE_VIEW(priv->treeview_presence_opt_params), NULL);
        goto CLEAN_UP;
    }

    is_child = gtk_tree_model_iter_parent (tree_model, &parent_iter, &iter);
    if (is_child)
    {
        gtk_tree_model_get (tree_model, &parent_iter,
                            TI_COLUMN_PRESENCE_LIST_HANDLE, &handle,
                            -1);

        gtk_tree_model_get (tree_model, &iter,
                            TI_COLUMN_PRESENCE_LIST_STATUS, &status,
                            -1);
    }
    else
    {
        gtk_tree_model_get (tree_model, &iter,
                            TI_COLUMN_PRESENCE_LIST_HANDLE, &handle,
                            TI_COLUMN_PRESENCE_LIST_STATUS, &status,
                            -1);
    }

    hash_key = g_strdup_printf ("%s-%s", handle, status);
    opt_params_list = (GtkListStore*) g_hash_table_lookup (priv->hashtable_presence_opt_params_list, hash_key);
    g_free (hash_key);

    gtk_tree_view_set_model (GTK_TREE_VIEW(priv->treeview_presence_opt_params), GTK_TREE_MODEL(opt_params_list));

    CLEAN_UP:
    g_free (handle);
    g_free (status);
}

/**
 * Presence Update
 */
static void
_ti_page_presence_presence_update (TIPagePresence* page_presence, GHashTable* presence_update)
{
    GArray* presence_update_array;
    guint i;
    TIHashEntry hash_entry;
    guint contact_handle;
    GValueArray* contact_presence;
    GValue* gvalue;
    guint timestamp;
    GHashTable* statuses;

    presence_update_array = ti_hash_table_to_array (presence_update);

    for (i = 0; i < presence_update_array->len; i++)
    {
        hash_entry = g_array_index(presence_update_array, TIHashEntry, i);

        contact_handle = GPOINTER_TO_UINT (hash_entry.key);
        contact_presence = (GValueArray*) (hash_entry.value);

        g_assert (contact_presence->n_values == 2);

        // First, remove current presence status for that contact (if any).
        _ti_page_presence_remove_presence (page_presence, contact_handle);

        gvalue = g_value_array_get_nth (contact_presence, 0);
        timestamp = g_value_get_uint (gvalue);

        gvalue = g_value_array_get_nth (contact_presence, 1);
        statuses = (GHashTable*) g_value_get_boxed (gvalue);
        g_assert (statuses != NULL);

        _ti_page_presence_add_presence (page_presence, contact_handle, timestamp, statuses);
    }

    // Clean up
    g_array_free (presence_update_array, TRUE);
}

/**
 * Remove Presence
 */
static void
_ti_page_presence_remove_presence (TIPagePresence* page_presence, guint contact_handle)
{
    TIPagePresencePrivate* priv = TI_PAGE_PRESENCE_GET_PRIVATE (page_presence);
    gboolean keep_going;
    GtkTreeIter iter;
    gchar* curr_handle_str = NULL;
    gchar* contact_handle_str = NULL;

    keep_going = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->presence_tree), &iter);
    if (!keep_going)
        return; // The tree is probably empty.

    contact_handle_str = g_strdup_printf ("%u", contact_handle);

    while (keep_going)
    {
        gtk_tree_model_get (GTK_TREE_MODEL (priv->presence_tree), &iter,
                            TI_COLUMN_PRESENCE_LIST_HANDLE, &curr_handle_str,
                            -1);

        if (g_str_equal (curr_handle_str, contact_handle_str))
        {
            gtk_tree_store_remove (priv->presence_tree, &iter);
            keep_going = FALSE;
        }

        g_free (curr_handle_str);

        if (keep_going)
            keep_going = gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->presence_tree), &iter);
    }

    g_free (contact_handle_str);
}

/**
 * Add Presence
 */
static void
_ti_page_presence_add_presence (TIPagePresence* page_presence, guint contact_handle, guint timestamp, GHashTable* statuses)
{
    TIPagePresencePrivate* priv = TI_PAGE_PRESENCE_GET_PRIVATE (page_presence);
    GArray* statuses_array = NULL;
    GtkTreeIter top_iter;
    GtkTreeIter child_iter;
    gchar* contact_handle_str = NULL;
    gchar* timestamp_str = NULL;
    TIHashEntry hash_entry;
    const gchar* status_id;
    guint i;
    GHashTable* opt_params;
    gchar* name;

    g_assert (g_hash_table_size (statuses) > 0);

    statuses_array = ti_hash_table_to_array (statuses);

    name = ti_handle_mapper_get_contact_handle_name (priv->handle_mapper, contact_handle);
    if (name == NULL)
    {
        // Fallback to its handle number
        name = g_strdup_printf ("%u", contact_handle);
    }

    contact_handle_str = g_strdup_printf ("%u", contact_handle);
    timestamp_str = g_strdup_printf ("%u", timestamp);

    hash_entry = g_array_index (statuses_array, TIHashEntry, 0);
    status_id = (gchar*) (hash_entry.key);
    opt_params = (GHashTable*) (hash_entry.value);

    gtk_tree_store_append (priv->presence_tree, &top_iter, NULL);
    gtk_tree_store_set (priv->presence_tree, &top_iter,
                        TI_COLUMN_PRESENCE_LIST_NAME, name,
                        TI_COLUMN_PRESENCE_LIST_HANDLE, contact_handle_str,
                        TI_COLUMN_PRESENCE_LIST_TIMESTAMP, timestamp_str,
                        TI_COLUMN_PRESENCE_LIST_STATUS, status_id,
                        -1);

    _ti_page_presence_add_presence_opt_params_to_list (page_presence,
                                                       contact_handle_str,
                                                       status_id,
                                                       opt_params);

    if (statuses_array->len > 1)
    {
        // The other statuses will be added as child elements.
        for (i = 1; i < statuses_array->len; i++)
        {
            hash_entry = g_array_index (statuses_array, TIHashEntry, i);
            status_id = (gchar*) (hash_entry.key);
            opt_params = (GHashTable*) (hash_entry.value);

            gtk_tree_store_append (priv->presence_tree, &child_iter, &top_iter);
            gtk_tree_store_set (priv->presence_tree, &child_iter,
                                TI_COLUMN_PRESENCE_LIST_STATUS, status_id,
                                -1);

            _ti_page_presence_add_presence_opt_params_to_list (page_presence,
                                                               contact_handle_str,
                                                               status_id,
                                                               opt_params);
        }
    }
    

    // Clean up
    g_array_free (statuses_array, TRUE);
    g_free (name);
    g_free (contact_handle_str);
    g_free (timestamp_str);
}

/**
 * Add Handle Status' Optional Parameters to List
 */
static void
_ti_page_presence_add_presence_opt_params_to_list (TIPagePresence* page_presence,
                                                   const gchar* handle,
                                                   const gchar* status,
                                                   GHashTable* opt_params)
{
    TIPagePresencePrivate* priv = TI_PAGE_PRESENCE_GET_PRIVATE (page_presence);
    GtkListStore* opt_params_list = NULL;
    GArray* opt_params_array = NULL;
    gchar* key;
    guint i;
    GtkTreeIter iter;
    TIHashEntry hash_entry;
    const gchar* opt_param_name;
    gchar* opt_param_value;

    key = g_strdup_printf ("%s-%s", handle, status);

    opt_params_list = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
    g_hash_table_insert (priv->hashtable_presence_opt_params_list, key, opt_params_list);
    g_object_ref (opt_params_list);

    opt_params_array = ti_hash_table_to_array (opt_params);

    for (i = 0; i < opt_params_array->len; i++)
    {
        hash_entry = g_array_index (opt_params_array, TIHashEntry, i);
        opt_param_name = (gchar*) hash_entry.key;
        opt_param_value = ti_value_to_string ((GValue*) hash_entry.value);

        gtk_list_store_append (opt_params_list, &iter);
        gtk_list_store_set (opt_params_list, &iter,
                            0, opt_param_name,
                            1, opt_param_value,
                            -1);

        g_free (opt_param_value);
    }

    // Clean up
    g_array_free (opt_params_array, TRUE);

}

/**
 * Request Presence
 */
static void
_ti_page_presence_request_presence (TIPagePresence* page_presence)
{
    TIPagePresencePrivate* priv = TI_PAGE_PRESENCE_GET_PRIVATE (page_presence);
    gboolean ok;
    GArray* handles = NULL;
    GError* error = NULL;

    ok = ti_dlg_handles_list_run (priv->dlg_handles_list, &handles);
    if (!ok)
        goto CLEAN_UP;

    ti_connection_ipresence_request_presence (priv->connection, handles, &error);
    if (error != NULL)
    {
        // TODO: Display a message or something.
    }

    CLEAN_UP:
    g_array_free (handles, TRUE);

    if (error != NULL)
        g_error_free (error);
}

/**
 * Clear Presence List
 */
static void _ti_page_presence_clear_presence_list (TIPagePresence* page_presence)
{
    TIPagePresencePrivate* priv = TI_PAGE_PRESENCE_GET_PRIVATE (page_presence);

    // Clear presence list
    gtk_tree_store_clear (priv->presence_tree);

    // Clear its optional parameters
    g_hash_table_destroy (priv->hashtable_presence_opt_params_list);
    priv->hashtable_presence_opt_params_list = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
}

/**
 * Add User Status
 */
static void
_ti_page_presence_add_user_status (TIPagePresence* page_presence)
{
    TIPagePresencePrivate* priv = TI_PAGE_PRESENCE_GET_PRIVATE (page_presence);
    GHashTable* opt_params;
    GError* error = NULL;

    opt_params = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, ti_value_destroy);

    gchar* status = NULL;
    ti_dlg_user_status_run_add (priv->dlg_user_status, &status);

    ti_connection_ipresence_add_status (priv->connection, status, opt_params, &error);
    if (error != NULL)
    {
        // TODO: Display a message or something.
    }

    // Clean up
    g_free (status);
    g_hash_table_destroy (opt_params);

    if (error != NULL)
        g_error_free (error);
}

/**
 * Clear User Status
 */
static void
_ti_page_presence_clear_user_status (TIPagePresence* page_presence)
{
    TIPagePresencePrivate* priv = TI_PAGE_PRESENCE_GET_PRIVATE (page_presence);
    GError* error = NULL;

    ti_connection_ipresence_clear_status (priv->connection, &error);
    if (error != NULL)
    {
        // TODO: Display a message or something.
    }

    // Clean up
    if (error != NULL)
        g_error_free (error);
}

/**
 * Remove User Status
 */
static void
_ti_page_presence_remove_user_status (TIPagePresence* page_presence)
{
    TIPagePresencePrivate* priv = TI_PAGE_PRESENCE_GET_PRIVATE (page_presence);
    GError* error = NULL;
    gchar* status = NULL;

    ti_dlg_user_status_run_remove (priv->dlg_user_status, &status);

    ti_connection_ipresence_remove_status (priv->connection, status, &error);
    if (error != NULL)
    {
        // TODO: Display a message or something.
    }

    // Clean up
    g_free (status);

    if (error != NULL)
        g_error_free (error);
}

/**
 * Handle Display Mode Changed
 */
static void
_ti_page_presence_handle_display_mode_changed (TIPagePresence* page_presence, guint handle_display_mode)
{
    TIPagePresencePrivate* priv = TI_PAGE_PRESENCE_GET_PRIVATE (page_presence);
    GtkTreeViewColumn* contact_handle_column;
    GtkCellRenderer* renderer;
    GList* renderers_list = NULL;

    contact_handle_column = gtk_tree_view_get_column (priv->presence_treeview, 0); // It's the first column.

    renderers_list = gtk_tree_view_column_get_cell_renderers (contact_handle_column);
    g_assert (g_list_length (renderers_list) == 1);

    renderer = GTK_CELL_RENDERER (renderers_list->data);

    if (handle_display_mode == TI_PREFERENCES_HANDLE_DISPLAY_HANDLE)
    {
        gtk_tree_view_column_set_title (contact_handle_column, "Handle");

        gtk_tree_view_column_set_attributes (contact_handle_column, renderer,
                                             "text", TI_COLUMN_PRESENCE_LIST_HANDLE,
                                             NULL);
    }
    else // TI_PREFERENCES_HANDLE_DISPLAY_NAME
    {
        gtk_tree_view_column_set_title (contact_handle_column, "Name");

        gtk_tree_view_column_set_attributes (contact_handle_column, renderer,
                                             "text", TI_COLUMN_PRESENCE_LIST_NAME,
                                             NULL);
    }

    // Clean up
    g_list_free (renderers_list);
}

Generated by  Doxygen 1.6.0   Back to index