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

ti-page-capabilities.c

/*
 * Telapathy Inspector - A Telepathy client which exposes Telepathy interfaces.
 *                       Meant to inspect and/or test connection managers.
 * 
 * ti-page-capabilities.c:
 * A GtkNotebook page exposing
 * org.freedesktop.Telepathy.Connection.Interface.Capabilities 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-capabilities.h"
#include "ti-page-priv.h"
#include "ti-preferences.h"
#include "ti-constants.h"
#include "ti-dlg-advertise-caps.h"
#include "ti-dlg-handles-list.h"
#include "ti-util.h"

#include <glade/glade.h>

enum {
    TI_COLUMN_CAPABILITIES_LIST_NAME = 0,
    TI_COLUMN_CAPABILITIES_LIST_CONTACT_HANDLE,
    TI_COLUMN_CAPABILITIES_LIST_GENERIC_FLAGS,
    TI_COLUMN_CAPABILITIES_LIST_SPECIFIC_FLAGS,
    TI_CAPABILITIES_LIST_N_COLUMNS
};


struct _TIPageCapabilitiesClass {
    TIPageClass parent;
};

G_DEFINE_TYPE (TIPageCapabilities, ti_page_capabilities, TI_TYPE_PAGE);

/* Function prototypes */
static void _ti_page_capabilities_setup_page (TIPage* page, GladeXML* glade_xml);
static void _ti_page_capabilities_restart_page (TIPage* page);
static void _ti_page_capabilities_build_treeview (TIPageCapabilities* self, GladeXML* glade_xml);
static void _ti_page_capabilities_handle_display_mode_changed (TIPageCapabilities* self, guint handle_display_mode);
static void _ti_page_capabilities_clear (TIPageCapabilities* self);
static void _ti_page_capabilities_capabilities_changed (TIPageCapabilities* self, GPtrArray* caps);
static void _ti_page_capabilities_get (TIPageCapabilities* self);
static void _ti_page_capabilities_set_capability (TIPageCapabilities* self,
                                                  guint handle, const gchar* channel_type,
                                                  guint generic_flags, guint specific_flags);
static gchar* _get_generic_flags_string (guint generic_flags);
static void _ti_page_capabilities_get_contact_row (TIPageCapabilities* self, GtkTreeIter* iter, guint handle);
static void _ti_page_capabilities_advertise (TIPageCapabilities* self);


/**
 * Instance private data.
 */
00071 struct _TIPageCapabilitiesPrivate {
    GtkWindow* parent_wnd;

    TIConnection* connection;
    TIPreferences* preferences;
    TIHandleMapper* handle_mapper;
    TIDlgHandlesList* dlg_handles_list;
    TIDlgAdvertiseCaps* dlg_advertise_caps;

    GtkTreeView* tree_view;
    GtkTreeStore* tree_store;
    GtkTreeSelection* tree_selection;
};
typedef struct _TIPageCapabilitiesPrivate TIPageCapabilitiesPrivate;

#define TI_PAGE_CAPABILITIES_GET_PRIVATE(object)  (G_TYPE_INSTANCE_GET_PRIVATE ((object), TI_TYPE_PAGE_CAPABILITIES, TIPageCapabilitiesPrivate))

/**
 * Drop all references to other objects.
 */
static void
ti_page_capabilities_dispose (GObject *object)
{
    TIPageCapabilities* self = TI_PAGE_CAPABILITIES (object);
    TIPageCapabilitiesPrivate* priv = TI_PAGE_CAPABILITIES_GET_PRIVATE (self);

    if (priv->connection != NULL)
    {
        g_signal_handlers_disconnect_by_func(priv->connection,
                                             G_CALLBACK (_ti_page_capabilities_capabilities_changed),
                                             self);

        g_object_unref (priv->connection);
        priv->connection = NULL;
    }

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

    TI_OBJ_UNREF (priv->handle_mapper);
    TI_OBJ_UNREF (priv->dlg_handles_list);
    TI_OBJ_UNREF (priv->dlg_advertise_caps);

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

/**
 * Class initialization.
 */
static void
ti_page_capabilities_class_init (TIPageCapabilitiesClass* page_capabilities_class)
{
      GObjectClass *gobject_class = G_OBJECT_CLASS (page_capabilities_class);
    TIPageClass* page_class = TI_PAGE_CLASS (page_capabilities_class);

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

    page_class->setup_page = _ti_page_capabilities_setup_page;
    page_class->restart_page = _ti_page_capabilities_restart_page;
            
      /* Add private */
      g_type_class_add_private (page_capabilities_class, sizeof (TIPageCapabilitiesPrivate));
}

/**
 * Instance initialization.
 */
static void
ti_page_capabilities_init (TIPageCapabilities* self)
{
    TIPageCapabilitiesPrivate *priv = TI_PAGE_CAPABILITIES_GET_PRIVATE (self);

    priv->connection = NULL;
    priv->preferences = ti_preferences_new ();
    priv->handle_mapper = NULL;
    priv->dlg_handles_list = NULL;
    priv->dlg_advertise_caps = NULL;
}

/**
 * Returns a new instance.
 */
TIPageCapabilities*
ti_page_capabilities_new (GtkWindow* parent_wnd, GtkNotebook* parent_notebook, TIConnection* connection, TIHandleMapper* handle_mapper) 
{
    TIPageCapabilities* page_capabilities;
    TIPageCapabilitiesPrivate *priv;

      page_capabilities = g_object_new (TI_TYPE_PAGE_CAPABILITIES, NULL);

    priv = TI_PAGE_CAPABILITIES_GET_PRIVATE (page_capabilities);

    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 (priv->parent_wnd, priv->handle_mapper, "Get Capabilities");
    priv->dlg_advertise_caps = ti_dlg_advertise_caps_new (priv->parent_wnd);

    g_signal_connect_swapped (priv->connection, "capabilities-changed",
                              G_CALLBACK (_ti_page_capabilities_capabilities_changed), page_capabilities);

    g_signal_connect_swapped (priv->preferences, "handle-display-mode-changed",
                              G_CALLBACK (_ti_page_capabilities_handle_display_mode_changed), page_capabilities);

    _ti_page_new ((TIPage**)&page_capabilities, parent_notebook, "page-capabilities.xml");

    return page_capabilities;
}

/**
 * Setup Page
 */
static void
_ti_page_capabilities_setup_page (TIPage* page, GladeXML* glade_xml)
{
    TIPageCapabilities* self = TI_PAGE_CAPABILITIES (page);
//    TIPageCapabilitiesPrivate* priv = TI_PAGE_CAPABILITIES_GET_PRIVATE (self);
    GtkWidget* widget;

    // Capabilities list
    _ti_page_capabilities_build_treeview (self, glade_xml);

    // Button "Get"
    widget = glade_xml_get_widget (glade_xml, "button_get");
    g_assert (widget != NULL && GTK_IS_BUTTON (widget));
    g_signal_connect_swapped (widget, "clicked", G_CALLBACK (_ti_page_capabilities_get), self);

    // Button "Advertise"
    widget = glade_xml_get_widget (glade_xml, "button_advertise");
    g_assert (widget != NULL && GTK_IS_BUTTON (widget));
    g_signal_connect_swapped (widget, "clicked", G_CALLBACK (_ti_page_capabilities_advertise), self);

    // Button "Clear"
    widget = glade_xml_get_widget (glade_xml, "button_clear");
    g_assert (widget != NULL && GTK_IS_BUTTON (widget));
    g_signal_connect_swapped (widget, "clicked", G_CALLBACK (_ti_page_capabilities_clear), self);
}

/**
 * Restart Page
 */
static void
_ti_page_capabilities_restart_page (TIPage* page)
{
    TIPageCapabilities* self = TI_PAGE_CAPABILITIES (page);
    TIPageCapabilitiesPrivate* priv = TI_PAGE_CAPABILITIES_GET_PRIVATE (self);

    gtk_tree_store_clear (priv->tree_store);
}

/**
 * Build Treeview
 */
static void
_ti_page_capabilities_build_treeview (TIPageCapabilities* self, GladeXML* glade_xml)
{
    TIPageCapabilitiesPrivate* priv = TI_PAGE_CAPABILITIES_GET_PRIVATE (self);
    GtkCellRenderer* renderer;
    GtkTreeViewColumn* column;
    GtkTreeSelection* selection;

    priv->tree_view = GTK_TREE_VIEW (glade_xml_get_widget(glade_xml, "treeview_capabilities"));
    g_assert (priv->tree_view != NULL && GTK_IS_TREE_VIEW (priv->tree_view));

    priv->tree_store = gtk_tree_store_new (TI_CAPABILITIES_LIST_N_COLUMNS,
                                           G_TYPE_STRING,    // name
                                           G_TYPE_UINT,  // contact handle
                                           G_TYPE_STRING,  // generic flags
                                           G_TYPE_STRING); // specific flags
    
    gtk_tree_view_set_model (priv->tree_view, GTK_TREE_MODEL (priv->tree_store));

    renderer = gtk_cell_renderer_text_new ();

    column = gtk_tree_view_column_new_with_attributes ("Name",
                                                        renderer,
                                                        "text", TI_COLUMN_CAPABILITIES_LIST_NAME,
                                                        NULL);
    gtk_tree_view_append_column (priv->tree_view, column);

    column = gtk_tree_view_column_new_with_attributes ("Generic",
                                                       renderer,
                                                       "text", TI_COLUMN_CAPABILITIES_LIST_GENERIC_FLAGS,
                                                       NULL);
    gtk_tree_view_append_column (priv->tree_view, column);

    column = gtk_tree_view_column_new_with_attributes ("Specific",
                                                       renderer,
                                                       "text", TI_COLUMN_CAPABILITIES_LIST_SPECIFIC_FLAGS,
                                                       NULL);
    gtk_tree_view_append_column (priv->tree_view, column);

    selection = gtk_tree_view_get_selection (priv->tree_view);
    gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
}

/**
 * Handle Display Mode Changed
 */
static void
_ti_page_capabilities_handle_display_mode_changed (TIPageCapabilities* self, guint handle_display_mode)
{
    TIPageCapabilitiesPrivate* priv = TI_PAGE_CAPABILITIES_GET_PRIVATE (self);
    GtkTreeIter iter;
    gboolean ok;
    guint handle;
    gchar* name;

    ok = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->tree_store), &iter);
    while (ok)
    {
        gtk_tree_model_get (GTK_TREE_MODEL (priv->tree_store), &iter,
                            TI_COLUMN_CAPABILITIES_LIST_CONTACT_HANDLE, &handle,
                            -1);

        if (handle_display_mode == TI_PREFERENCES_HANDLE_DISPLAY_HANDLE)
        {
            name = NULL;
        }
        else
        {
            name = ti_handle_mapper_get_contact_handle_name (priv->handle_mapper, handle);
        }

        if (name == NULL)
            name = g_strdup_printf ("%u", handle);

        gtk_tree_store_set (priv->tree_store, &iter,
                            TI_COLUMN_CAPABILITIES_LIST_NAME, name,
                            -1);

        g_free (name);

        ok = gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->tree_store), &iter);
    }
}

/**
 * Clear
 */
static void
_ti_page_capabilities_clear (TIPageCapabilities* self)
{
    TIPageCapabilitiesPrivate* priv = TI_PAGE_CAPABILITIES_GET_PRIVATE (self);

    gtk_tree_store_clear (priv->tree_store);
}

/**
 * Capabilities Changed
 */
static void
_ti_page_capabilities_capabilities_changed (TIPageCapabilities* self, GPtrArray* caps)
{
    guint i;
    GValueArray* cap_change;
    guint handle;
    const gchar* channel_type;
    guint generic_flags;
    guint specific_flags;

    for (i = 0; i < caps->len; i++)
    {
        cap_change = (GValueArray*) g_ptr_array_index (caps, i);

        handle = g_value_get_uint (g_value_array_get_nth (cap_change, 0));
        channel_type = g_value_get_string (g_value_array_get_nth (cap_change, 1));
        generic_flags = g_value_get_uint (g_value_array_get_nth (cap_change, 3));
        specific_flags = g_value_get_uint (g_value_array_get_nth (cap_change, 5));

        _ti_page_capabilities_set_capability (self, handle, channel_type, generic_flags, specific_flags);
    }
}

/**
 * Get
 */
static void
_ti_page_capabilities_get (TIPageCapabilities* self)
{
    TIPageCapabilitiesPrivate *priv = TI_PAGE_CAPABILITIES_GET_PRIVATE (self);
    gboolean ok;
    GArray* handles = NULL;
    GPtrArray* capabilities = NULL;
    GError* error = NULL;
    guint i;
    GValueArray* capability;
    guint handle;
    const gchar* channel_type;
    guint generic_flags;
    guint specific_flags;

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

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

    for (i = 0; i < capabilities->len; i++)
    {
        capability = (GValueArray*) g_ptr_array_index (capabilities, i);

        handle = g_value_get_uint (g_value_array_get_nth (capability, 0));
        channel_type = g_value_get_string (g_value_array_get_nth (capability, 1));
        generic_flags = g_value_get_uint (g_value_array_get_nth (capability, 2));
        specific_flags = g_value_get_uint (g_value_array_get_nth (capability, 3));

        _ti_page_capabilities_set_capability (self, handle, channel_type, generic_flags, specific_flags);

        g_value_array_free (capability);
    }

    CLEAN_UP:
    g_array_free (handles, TRUE);
    g_ptr_array_free (capabilities, TRUE);

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

/**
 * Set Capability
 */
static void
_ti_page_capabilities_set_capability (TIPageCapabilities* self,
                                      guint handle, const gchar* channel_type,
                                      guint generic_flags, guint specific_flags)
{
    TIPageCapabilitiesPrivate* priv = TI_PAGE_CAPABILITIES_GET_PRIVATE (self);
    GtkTreeIter iter;
    GtkTreeIter child_iter;
    gboolean ok;
    gboolean found = FALSE;
    gchar* generic_flags_str = NULL;
    gchar* specific_flags_str = NULL;
    gchar* name = NULL;

    _ti_page_capabilities_get_contact_row (self, &iter, handle);

    // Look for channel type's row for the given contact
    found = FALSE;
    ok = gtk_tree_model_iter_children (GTK_TREE_MODEL (priv->tree_store), &child_iter, &iter);
    while (ok && !found)
    {
        gtk_tree_model_get (GTK_TREE_MODEL (priv->tree_store), &child_iter,
                            TI_COLUMN_CAPABILITIES_LIST_NAME, &name,
                            -1);

        if (g_str_equal (name, channel_type))
        {
            found = TRUE;
        }
        else
        {
            ok = gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->tree_store), &child_iter);
        }

        g_free (name);
        name = NULL;
    }

    if (!found)
    {
        // Create a new row for our contact's channel type
        gtk_tree_store_append (priv->tree_store, &child_iter, &iter);
    }

    generic_flags_str = _get_generic_flags_string (generic_flags);
    specific_flags_str = g_strdup_printf ("%u", specific_flags);

    gtk_tree_store_set (priv->tree_store, &child_iter,
                        TI_COLUMN_CAPABILITIES_LIST_NAME, channel_type,
                        TI_COLUMN_CAPABILITIES_LIST_GENERIC_FLAGS, generic_flags_str,
                        TI_COLUMN_CAPABILITIES_LIST_SPECIFIC_FLAGS, specific_flags_str,
                        -1);

    // Clean up
    g_free (generic_flags_str);
    g_free (specific_flags_str);
}

/**
 * Get Generic Flags String
 */
static gchar*
_get_generic_flags_string (guint generic_flags)
{
    GString* string = g_string_new (NULL);

    if ((generic_flags & TI_CONNECTION_CAPABILITY_FLAG_CREATE) != 0)
    {
        g_string_append (string, "Create");
    }

    if ((generic_flags & TI_CONNECTION_CAPABILITY_FLAG_INVITE) != 0)
    {
        if (string->len > 0)
            g_string_append (string, " ");

        g_string_append (string, "Invite");
    }

    return g_string_free (string, FALSE);
}

/**
 * Get Contact Row
 *
 * If the specified contact doesn't have a row, a new one will be created for him.
 */
static void
_ti_page_capabilities_get_contact_row (TIPageCapabilities* self, GtkTreeIter* iter, guint handle)
{
    TIPageCapabilitiesPrivate* priv = TI_PAGE_CAPABILITIES_GET_PRIVATE (self);
    gboolean ok;
    gboolean found = FALSE;
    guint curr_handle;
    gchar* handle_name;

    // Look for the contact's row
    ok = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->tree_store), iter);
    while (ok && !found)
    {
        gtk_tree_model_get (GTK_TREE_MODEL (priv->tree_store), iter,
                            TI_COLUMN_CAPABILITIES_LIST_CONTACT_HANDLE, &curr_handle,
                            -1);

        if (curr_handle == handle)
        {
            found = TRUE;
        }
        else
        {
            ok = gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->tree_store), iter);
        }
    }

    if (!found)
    {
        // Create a new row for that handle
        gtk_tree_store_append (priv->tree_store, iter, NULL);

        if (ti_preferences_get_handle_display_mode (priv->preferences) ==
            TI_PREFERENCES_HANDLE_DISPLAY_HANDLE)
        {
            handle_name = NULL;
        }
        else
        {
            handle_name = ti_handle_mapper_get_contact_handle_name (priv->handle_mapper, handle);
        }

        if (handle_name == NULL)
            handle_name = g_strdup_printf ("%u", handle);

        gtk_tree_store_set (priv->tree_store, iter,
                            TI_COLUMN_CAPABILITIES_LIST_NAME, handle_name,
                            TI_COLUMN_CAPABILITIES_LIST_CONTACT_HANDLE, handle,
                            -1);
        g_free (handle_name);
    }
}

/**
 * Advertise
 */
static void
_ti_page_capabilities_advertise (TIPageCapabilities* self)
{
    TIPageCapabilitiesPrivate* priv = TI_PAGE_CAPABILITIES_GET_PRIVATE (self);
    GPtrArray* add_caps = NULL;
    gchar** remove_caps = NULL;
    gboolean ok;
    GError* error = NULL;

    ok = ti_dlg_advertise_caps_run (priv->dlg_advertise_caps, &add_caps, &remove_caps);
    if (!ok)
        goto CLEAN_UP;
    
    ti_connection_icapabilities_advertise_capabilities (priv->connection, add_caps, remove_caps, &error);
    if (error != NULL)
    {
        // TODO: Display an error message or something.
    }

    CLEAN_UP:
    if (add_caps != NULL)
        g_ptr_array_free (add_caps, TRUE);

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

    g_strfreev (remove_caps);
}

Generated by  Doxygen 1.6.0   Back to index