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

ti-page-room-list.c

/*
 * Telapathy Inspector - A Telepathy client which exposes Telepathy interfaces.
 *                       Meant to inspect and/or test connection managers.
 * 
 * ti-page-room-list.c:
 * A GtkNotebook page exposing
 * org.freedesktop.Telepathy.Channel.Type.RoomList 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-room-list.h"
#include "ti-page-priv.h"
#include "ti-constants.h"
#include "ti-util.h"
#include "ti-preferences.h"

#include <glade/glade.h>

enum {
    TI_COLUMN_ROOM_LIST_NAME = 0,
    TI_COLUMN_ROOM_LIST_HANDLE,
    TI_COLUMN_ROOM_LIST_CHANNEL_TYPE,
    TI_ROOM_LIST_N_COLUMNS
};

enum {
    TI_COLUMN_INFO_NAME = 0,
    TI_COLUMN_INFO_VALUE,
    TI_INFO_N_COLUMNS
};


struct _TIPageRoomListClass {
    TIPageClass parent;
};

G_DEFINE_TYPE (TIPageRoomList, ti_page_room_list, TI_TYPE_PAGE);

/* Function prototypes */
static void _ti_page_room_list_setup_page (TIPage* page, GladeXML* glade_xml);
static void _ti_page_room_list_restart_page (TIPage* page);
static void _ti_page_room_list_build_tree_view_rooms (TIPageRoomList* self, GladeXML* glade_xml);
static void _ti_page_room_list_build_tree_view_info (TIPageRoomList* self, GladeXML* glade_xml);
static void _ti_page_room_list_handle_display_mode_changed (TIPageRoomList* self, guint handle_display_mode);
static void _ti_page_room_list_get_listing_rooms (TIPageRoomList* self);
static void _ti_page_room_list_list_rooms (TIPageRoomList* self);
static void _ti_page_room_list_got_rooms (TIPageRoomList* self, GPtrArray* rooms);
static void _ti_page_room_list_listing_rooms (TIPageRoomList* self, gboolean is_listing);
static void _ti_page_room_list_add_room (TIPageRoomList* self, guint handle, const gchar* channel_type);
static void _ti_page_room_list_show_info_of_selected_room (TIPageRoomList* self);
static void _ti_page_room_list_add_room_info (TIPageRoomList* self, guint handle, GHashTable* info);


/**
 * Instance private data.
 */
00073 struct _TIPageRoomListPrivate {

    TIChannel* channel;
    TIPreferences* preferences;
    TIHandleMapper* handle_mapper;

    GtkTreeView* tree_view_rooms;
    GtkListStore* list_store_rooms;
    GtkTreeSelection* selection_rooms;

    GtkTreeView* tree_view_info;

    // Maps a room handle with its list_store room info.
    GHashTable* hashtable_room_info;

    GtkLabel* label_listing_rooms;
};
typedef struct _TIPageRoomListPrivate TIPageRoomListPrivate;

#define TI_PAGE_ROOM_LIST_GET_PRIVATE(object)  (G_TYPE_INSTANCE_GET_PRIVATE ((object), TI_TYPE_PAGE_ROOM_LIST, TIPageRoomListPrivate))

/**
 * Drop all references to other objects.
 */
static void
ti_page_room_list_dispose (GObject *object)
{
    TIPageRoomList* self = TI_PAGE_ROOM_LIST (object);
    TIPageRoomListPrivate* priv = TI_PAGE_ROOM_LIST_GET_PRIVATE (self);

    if (priv->channel != NULL)
    {
        g_signal_handlers_disconnect_by_func(priv->channel,
                                             G_CALLBACK (_ti_page_room_list_got_rooms),
                                             self);

        g_signal_handlers_disconnect_by_func(priv->channel,
                                             G_CALLBACK (_ti_page_room_list_listing_rooms),
                                             self);

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

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

    TI_OBJ_UNREF (priv->handle_mapper);

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

/**
 * Finalizes the object, marking the memory as ready for reuse
 */
static void
ti_page_room_list_finalize (GObject *object)
{
    TIPageRoomList* self = TI_PAGE_ROOM_LIST (object);
    TIPageRoomListPrivate* priv = TI_PAGE_ROOM_LIST_GET_PRIVATE (self);

    g_hash_table_destroy (priv->hashtable_room_info);

    G_OBJECT_CLASS (ti_page_room_list_parent_class)->finalize (object);
}

/**
 * Class initialization.
 */
static void
ti_page_room_list_class_init (TIPageRoomListClass* page_room_list_class)
{
    GObjectClass *gobject_class = G_OBJECT_CLASS (page_room_list_class);
    TIPageClass* page_class = TI_PAGE_CLASS (page_room_list_class);

    /* override base object methods */ 
    gobject_class->dispose = ti_page_room_list_dispose;
    gobject_class->finalize = ti_page_room_list_finalize;

    page_class->setup_page = _ti_page_room_list_setup_page;
    page_class->restart_page = _ti_page_room_list_restart_page;

    /* Add private */
    g_type_class_add_private (page_room_list_class, sizeof (TIPageRoomListPrivate));
}

/**
 * Instance initialization.
 */
static void
ti_page_room_list_init (TIPageRoomList* self)
{
    TIPageRoomListPrivate *priv = TI_PAGE_ROOM_LIST_GET_PRIVATE (self);

    priv->channel = NULL;
    priv->preferences = ti_preferences_new ();
    priv->handle_mapper = NULL;
    priv->hashtable_room_info = g_hash_table_new_full (g_int_hash, g_int_equal, g_free, g_object_unref);
}

/**
 * Returns a new instance.
 */
TIPageRoomList*
ti_page_room_list_new (GtkNotebook* parent_notebook, TIChannel* channel, TIHandleMapper* handle_mapper) 
{
    TIPageRoomList* page_room_list;
    TIPageRoomListPrivate *priv;

    page_room_list = g_object_new (TI_TYPE_PAGE_ROOM_LIST, NULL);

    priv = TI_PAGE_ROOM_LIST_GET_PRIVATE (page_room_list);

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

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

    g_signal_connect_swapped (priv->preferences, "handle-display-mode-changed",
                                G_CALLBACK (_ti_page_room_list_handle_display_mode_changed), page_room_list);

    g_signal_connect_swapped (priv->channel, "got-rooms",
                              G_CALLBACK (_ti_page_room_list_got_rooms), page_room_list);

    g_signal_connect_swapped (priv->channel, "listing-rooms",
                              G_CALLBACK (_ti_page_room_list_listing_rooms), page_room_list);

    _ti_page_new ((TIPage**)&page_room_list, parent_notebook, "page-room-list.xml");

    return page_room_list;
}

/**
 * Setup Page
 */
static void
_ti_page_room_list_setup_page (TIPage* page, GladeXML* glade_xml)
{
    TIPageRoomList* self = TI_PAGE_ROOM_LIST (page);
    TIPageRoomListPrivate* priv = TI_PAGE_ROOM_LIST_GET_PRIVATE (self);
    GtkWidget* widget;

    // Room list
    _ti_page_room_list_build_tree_view_rooms (self, glade_xml);

    // Room Info Tree View
    _ti_page_room_list_build_tree_view_info (self, glade_xml);

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

    // Button "List Rooms"
    widget = glade_xml_get_widget (glade_xml, "button_list_rooms");
    g_assert (widget != NULL && GTK_IS_BUTTON (widget));
    g_signal_connect_swapped (widget, "clicked", G_CALLBACK (_ti_page_room_list_list_rooms), self);

    // Label listing_rooms
    priv->label_listing_rooms = (GtkLabel*) glade_xml_get_widget (glade_xml, "label_listing_rooms_value");
    g_assert (priv->label_listing_rooms != NULL && GTK_IS_LABEL (priv->label_listing_rooms));
    _ti_page_room_list_get_listing_rooms (self); // Init its value
}

/**
 * Restart Page
 */
static void
_ti_page_room_list_restart_page (TIPage* page)
{
    TIPageRoomList* self = TI_PAGE_ROOM_LIST (page);
    TIPageRoomListPrivate* priv = TI_PAGE_ROOM_LIST_GET_PRIVATE (self);

    gtk_list_store_clear (priv->list_store_rooms);

    _ti_page_room_list_get_listing_rooms (self);
}

/**
 * Build Treeview Rooms
 */
static void
_ti_page_room_list_build_tree_view_rooms (TIPageRoomList* self, GladeXML* glade_xml)
{
    TIPageRoomListPrivate* priv = TI_PAGE_ROOM_LIST_GET_PRIVATE (self);
    GtkCellRenderer* renderer;
    GtkTreeViewColumn* column;

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

    priv->list_store_rooms = gtk_list_store_new (TI_ROOM_LIST_N_COLUMNS,
                                                 G_TYPE_STRING,  // name
                                                 G_TYPE_UINT,    // handle
                                                 G_TYPE_STRING); // channel type

    gtk_tree_view_set_model (priv->tree_view_rooms, GTK_TREE_MODEL (priv->list_store_rooms));

    renderer = gtk_cell_renderer_text_new ();

    if (ti_preferences_get_handle_display_mode (priv->preferences) ==
        TI_PREFERENCES_HANDLE_DISPLAY_HANDLE)
    {
        column = gtk_tree_view_column_new_with_attributes ("Handle",
                                                           renderer,
                                                           "text", TI_COLUMN_ROOM_LIST_HANDLE,
                                                           NULL);
    }
    else
    {
        column = gtk_tree_view_column_new_with_attributes ("Name",
                                                           renderer,
                                                           "text", TI_COLUMN_ROOM_LIST_NAME,
                                                           NULL);
    }
    gtk_tree_view_append_column (priv->tree_view_rooms, column);

    column = gtk_tree_view_column_new_with_attributes ("Channel Type",
                                                       renderer,
                                                       "text", TI_COLUMN_ROOM_LIST_CHANNEL_TYPE,
                                                       NULL);
    gtk_tree_view_append_column (priv->tree_view_rooms, column);

    priv->selection_rooms = gtk_tree_view_get_selection (priv->tree_view_rooms);

    g_signal_connect_swapped (priv->selection_rooms, "changed",
                              G_CALLBACK (_ti_page_room_list_show_info_of_selected_room),
                              self);

    gtk_tree_selection_set_mode (priv->selection_rooms, GTK_SELECTION_SINGLE);
}

/**
 * Build Tree View Info
 */
static void
_ti_page_room_list_build_tree_view_info (TIPageRoomList* self, GladeXML* glade_xml)
{
    TIPageRoomListPrivate* priv = TI_PAGE_ROOM_LIST_GET_PRIVATE (self);
    GtkCellRenderer* renderer;
    GtkTreeViewColumn* column;
    GtkTreeSelection* selection;

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

    renderer = gtk_cell_renderer_text_new ();

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

    column = gtk_tree_view_column_new_with_attributes ("Value",
                                                       renderer,
                                                       "text", TI_COLUMN_INFO_VALUE,
                                                       NULL);
    gtk_tree_view_append_column (priv->tree_view_info, column);

    selection = gtk_tree_view_get_selection (priv->tree_view_info);
    gtk_tree_selection_set_mode (selection, GTK_SELECTION_NONE);
}

/**
 * Handle Display Mode Changed
 */
/*static void
_ti_page_room_list_handle_display_mode_changed (TIPageRoomList* self, guint handle_display_mode)
{
}*/

/**
 * Get ListingRooms
 */
static void
_ti_page_room_list_get_listing_rooms (TIPageRoomList* self)
{
    TIPageRoomListPrivate* priv = TI_PAGE_ROOM_LIST_GET_PRIVATE (self);
    GError* error = NULL;
    gboolean is_listing;

    is_listing = ti_channel_typeroomlist_get_listing_rooms (priv->channel, &error);
    if (error != NULL)
    {
        // TODO: Display a message or something.
        gtk_label_set_text (priv->label_listing_rooms, "ERROR");
        g_error_free (error);
        return;
    }

    if (is_listing)
    {
        gtk_label_set_text (priv->label_listing_rooms, "Yes");
    }
    else
    {
        gtk_label_set_text (priv->label_listing_rooms, "No");
    }
}

/**
 * List Rooms
 */
static void
_ti_page_room_list_list_rooms (TIPageRoomList* self)
{
    TIPageRoomListPrivate* priv = TI_PAGE_ROOM_LIST_GET_PRIVATE (self);
    GError* error = NULL;

    gtk_list_store_clear (priv->list_store_rooms);

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

/**
 * Got Rooms
 */
static void
_ti_page_room_list_got_rooms (TIPageRoomList* self, GPtrArray* rooms)
{
    guint i;
    GValueArray* room;
    GValue* value;
    guint handle;
    const gchar* channel_type;
    GHashTable* info;

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

        value = g_value_array_get_nth (room, 0);
        handle = g_value_get_uint (value);

        value = g_value_array_get_nth (room, 1);
        channel_type = g_value_get_string (value);

        value = g_value_array_get_nth (room, 2);
        info = (GHashTable*) g_value_get_boxed (value);

        _ti_page_room_list_add_room (self, handle, channel_type);
        _ti_page_room_list_add_room_info (self, handle, info);
    }
}

/**
 * Add Room
 */
static void
_ti_page_room_list_add_room (TIPageRoomList* self, guint handle, const gchar* channel_type)
{
    TIPageRoomListPrivate* priv = TI_PAGE_ROOM_LIST_GET_PRIVATE (self);
    gchar* room_name;
    GtkTreeIter iter;
    gboolean ok;
    gboolean found = FALSE;
    guint curr_handle;

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

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

    if (!found)
    {
        // Create a new row for that handle
        gtk_list_store_append (priv->list_store_rooms, &iter);
    }

    // Get its name
    room_name = ti_handle_mapper_get_room_handle_name (priv->handle_mapper, handle);
    if (room_name == NULL)
    {
        room_name = g_strdup_printf ("%u", handle);
    }

    // Set row contents
    gtk_list_store_set (priv->list_store_rooms, &iter,
                        TI_COLUMN_ROOM_LIST_NAME, room_name,
                        TI_COLUMN_ROOM_LIST_HANDLE, handle,
                        TI_COLUMN_ROOM_LIST_CHANNEL_TYPE, channel_type,
                        -1);

    // Clean up
    g_free (room_name);
}

/**
 * Listing Rooms
 */
static void
_ti_page_room_list_listing_rooms (TIPageRoomList* self, gboolean is_listing)
{
    TIPageRoomListPrivate* priv = TI_PAGE_ROOM_LIST_GET_PRIVATE (self);

    if (is_listing)
    {
        gtk_label_set_text (priv->label_listing_rooms, "Yes");
    }
    else
    {
        gtk_label_set_text (priv->label_listing_rooms, "No");
    }
}

/**
 * Show Info Of Selected Room
 */
static void
_ti_page_room_list_show_info_of_selected_room (TIPageRoomList* self)
{
    TIPageRoomListPrivate* priv = TI_PAGE_ROOM_LIST_GET_PRIVATE (self);
    gboolean has_selection;
    GtkTreeIter iter;
    GtkTreeModel* tree_model = NULL;
    guint handle;
    gint hash_key;
    GtkListStore* room_info = NULL;

    has_selection = gtk_tree_selection_get_selected (priv->selection_rooms, &tree_model, &iter);
    if (!has_selection)
    {
        gtk_tree_view_set_model (GTK_TREE_VIEW (priv->tree_view_info), NULL);
        return;
    }

    gtk_tree_model_get (tree_model, &iter,
                        TI_COLUMN_ROOM_LIST_HANDLE, &handle,
                        -1);

    hash_key = (gint) handle;
    room_info = (GtkListStore*) g_hash_table_lookup (priv->hashtable_room_info, &hash_key);
    g_assert (room_info != NULL);

    // GtkTreeView doesn't increase the ref count but do decreases it
    // when not using the model anynore.
    g_object_ref (room_info);
    gtk_tree_view_set_model (GTK_TREE_VIEW (priv->tree_view_info), GTK_TREE_MODEL (room_info));
}

/**
 * Add Room Info
 */
static void
_ti_page_room_list_add_room_info (TIPageRoomList* self, guint handle, GHashTable* info)
{
    TIPageRoomListPrivate* priv = TI_PAGE_ROOM_LIST_GET_PRIVATE (self);
    GArray* info_array = NULL;
    guint i;
    TIHashEntry hash_entry;
    GtkListStore* list_store;
    GtkTreeIter iter;
    gint* hash_key = NULL;
    gchar* value_str = NULL;
    const GValue* value;

    info_array = ti_hash_table_to_array (info);
    g_assert (info_array != NULL);

    list_store = gtk_list_store_new (TI_INFO_N_COLUMNS,
                                     G_TYPE_STRING, // name
                                     G_TYPE_STRING); // value

    hash_key = g_new (gint, 1);
    *hash_key = (gint) handle;
    g_hash_table_insert (priv->hashtable_room_info, hash_key, list_store);

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

        value = (GValue*) hash_entry.value;
        value_str = ti_value_to_string (value);

        gtk_list_store_append (list_store, &iter);
        gtk_list_store_set (list_store, &iter,
                            TI_COLUMN_INFO_NAME, hash_entry.key,
                            TI_COLUMN_INFO_VALUE, value_str,
                            -1);

        g_free (value_str);
    }

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

/**
 * Handle Display Mode Changed
 */
static void
_ti_page_room_list_handle_display_mode_changed (TIPageRoomList* self, guint handle_display_mode)
{
    TIPageRoomListPrivate* priv = TI_PAGE_ROOM_LIST_GET_PRIVATE (self);
    GtkTreeViewColumn* handle_column;
    GtkCellRenderer* renderer;
    GList* renderers_list = NULL;

    g_assert (self != NULL && TI_IS_PAGE_ROOM_LIST (self));

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

    renderers_list = gtk_tree_view_column_get_cell_renderers (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 (handle_column, "Handle");

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

        gtk_tree_view_column_set_attributes (handle_column, renderer,
                                             "text", TI_COLUMN_ROOM_LIST_NAME,
                                             NULL);
    }

    // Clean up
    g_list_free (renderers_list);
}

Generated by  Doxygen 1.6.0   Back to index