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

ti-wnd-channel.c

/*
 * Telapathy Inspector - A Telepathy client which exposes Telepathy interfaces.
 *                       Meant to inspect and/or test connection managers.
 * 
 * ti-wnd-channel.c:
 * Channel Window - UI to expose org.freedesktop.Telepathy.Channel functionality
 * 
 * Copyright (C) 2006, 2007 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-wnd-channel.h"
#include "ti-page-channel-group.h"
#include "ti-page-channel-text.h"
#include "ti-page-properties.h"
#include "ti-page-room-list.h"
#include "ti-config.h"
#include "ti-preferences.h"
#include "ti-constants.h"
#include "ti-util.h"

#include <glade/glade.h>
#include <string.h>

struct _TIWndChannelClass {
    GObjectClass parent;
    /* class members */
    guint close_wnd_id;
};

G_DEFINE_TYPE (TIWndChannel, ti_wnd_channel, G_TYPE_OBJECT);

/* Function prototypes */
static gboolean on_delete_window (TIWndChannel* wnd_channel, GdkEvent  *event);
static void _ti_wnd_channel_setup_first_page (TIWndChannel* wnd_channel);
static void _ti_wnd_channel_build_interfaces_treeview(TIWndChannel* wnd_channel);
static void _ti_wnd_channel_fill_interfaces_list (TIWndChannel* wnd_channel);
static void _ti_wnd_channel_close_channel (TIWndChannel* wnd_channel);
static void _ti_wnd_channel_add_interface_pages (TIWndChannel* wnd_channel);
static void _ti_wnd_channel_add_interface_page (TIWndChannel* wnd_channel, gchar* interface_name);
static gchar* _get_handle_type_str (guint handle_type);
static void _ti_wnd_channel_close_window (TIWndChannel* wnd_channel);
static void _ti_wnd_channel_setup_type_interface_page (TIWndChannel* wnd_channel);
static void _ti_wnd_channel_handle_display_mode_changed (TIWndChannel* wnd_channel, guint handle_display_mode);

/**
 * Instance private data.
 */
00063 struct _TIWndChannelPrivate {
    TIHandleMapper* handle_mapper;
    TIPreferences* preferences;

    GtkWindow* parent;

    GladeXML* glade_xml;

    GtkWidget* window;
    GtkNotebook* notebook;

    guint self_handle_type;
    guint self_handle_number;

    GtkLabel* label_handle_number;
    GtkLabel* label_handle_number_value;
    GtkWidget* button_close;

    GtkListStore* interfaces_list;

    TIChannel* channel;

    TIPageChannelGroup* page_group;
    TIPageRoomList* page_room_list;
    TIPageChannelText* page_text;
    TIPageProperties* page_properties;

    gboolean should_close_window;
};
typedef struct _TIWndChannelPrivate TIWndChannelPrivate;

#define TI_WND_CHANNEL_GET_PRIVATE(object)  (G_TYPE_INSTANCE_GET_PRIVATE ((object), TI_TYPE_WND_CHANNEL, TIWndChannelPrivate))

/**
 * Drop all references to other objects.
 */
static void
ti_wnd_channel_dispose (GObject *object)
{
    TIWndChannel *wnd_channel = TI_WND_CHANNEL (object);
    TIWndChannelPrivate *priv = TI_WND_CHANNEL_GET_PRIVATE (wnd_channel);

    TI_OBJ_UNREF (priv->handle_mapper);

    if (priv->preferences != NULL)
    {
        g_signal_handlers_disconnect_by_func (priv->preferences,
                                              G_CALLBACK (_ti_wnd_channel_handle_display_mode_changed),
                                              wnd_channel);

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

    if (priv->window != NULL)
    {
        gtk_widget_hide_all (priv->window);
    }

    TI_OBJ_UNREF (priv->glade_xml);
    TI_OBJ_UNREF (priv->channel);
    TI_OBJ_UNREF (priv->page_group);
    TI_OBJ_UNREF (priv->page_room_list);
    TI_OBJ_UNREF (priv->page_text);
    TI_OBJ_UNREF (priv->page_properties);

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

/**
 * Class initialization.
 */
static void
ti_wnd_channel_class_init (TIWndChannelClass *ti_wnd_channel_class)
{
    GObjectClass *gobject_class = G_OBJECT_CLASS (ti_wnd_channel_class);

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

    /* Add private */
    g_type_class_add_private (ti_wnd_channel_class, sizeof (TIWndChannelPrivate));

    /* Signals */

    /* Emitted when the window is closed. */
    ti_wnd_channel_class->close_wnd_id =
        g_signal_newv ("close-wnd",
                       G_TYPE_FROM_CLASS (ti_wnd_channel_class),
                       G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
                       NULL /* class closure */,
                       NULL /* accumulator */,
                       NULL /* accu_data */,
                       g_cclosure_marshal_VOID__VOID,
                       G_TYPE_NONE /* return_type */,
                       0     /* n_params */,
                       NULL  /* param_types */);
}

/**
 * Instance initialization.
 */
static void
ti_wnd_channel_init (TIWndChannel *ti_wnd_channel)
{
    TIWndChannelPrivate *priv = TI_WND_CHANNEL_GET_PRIVATE (ti_wnd_channel);

    priv->self_handle_type = 0;
    priv->self_handle_number = 0;
    priv->handle_mapper = NULL;
    priv->preferences = ti_preferences_new ();
    priv->glade_xml = NULL;
    priv->window = NULL;
    priv->notebook = NULL;
    priv->button_close = NULL;
    priv->channel = NULL;
    priv->page_group = NULL;
    priv->page_room_list = NULL;
    priv->page_text = NULL;
    priv->page_properties = NULL;
    priv->should_close_window = FALSE;
}

/**
 * Returns a new instance.
 */
TIWndChannel*
ti_wnd_channel_new (GtkWindow* parent, TIChannel* channel, TIHandleMapper* handle_mapper)
{
    TIWndChannel* wnd_channel = NULL;
    TIWndChannelPrivate *priv = NULL;
    gchar* glade_file_path = NULL;

    g_assert (channel != NULL);
    g_assert (parent != NULL);

    wnd_channel = g_object_new (TI_TYPE_WND_CHANNEL, NULL);

    priv = TI_WND_CHANNEL_GET_PRIVATE (wnd_channel);
    priv->parent = parent;

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

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

    glade_file_path = g_strdup_printf ("%s%s", TI_DATA_DIR_PREFIX, "wnd-channel.xml");

    priv->glade_xml = glade_xml_new (glade_file_path, NULL, NULL);
    if (priv->glade_xml == NULL)
    {
        g_critical ("Error loading glade file \"%s\".", glade_file_path);
        g_object_unref (wnd_channel);
        wnd_channel = NULL;
        goto CLEAN_UP;
    }

    priv->window = glade_xml_get_widget (priv->glade_xml, "window_channel");
    g_assert (GTK_IS_WINDOW (priv->window));

    priv->notebook = GTK_NOTEBOOK (glade_xml_get_widget (priv->glade_xml, "notebook"));
    g_assert (GTK_IS_NOTEBOOK (priv->notebook));

    g_signal_connect_swapped (priv->channel, "closed", G_CALLBACK (_ti_wnd_channel_close_window), wnd_channel);

    g_signal_connect_swapped (priv->window, "delete-event", G_CALLBACK (on_delete_window), wnd_channel);

    gtk_window_set_transient_for (GTK_WINDOW (priv->window), GTK_WINDOW (priv->parent));

    g_signal_connect_swapped (priv->preferences, "handle-display-mode-changed",
                              G_CALLBACK (_ti_wnd_channel_handle_display_mode_changed), wnd_channel);

    _ti_wnd_channel_setup_first_page (wnd_channel);
    _ti_wnd_channel_setup_type_interface_page (wnd_channel);
    _ti_wnd_channel_add_interface_pages (wnd_channel);

    CLEAN_UP:
    g_free (glade_file_path);

    return wnd_channel;
}

/**
 * Setup First Page - Helper Function
 */
static void
_ti_wnd_channel_setup_first_page (TIWndChannel* wnd_channel)
{
    TIWndChannelPrivate *priv = TI_WND_CHANNEL_GET_PRIVATE (wnd_channel);
    GtkWidget* first_page;
    GtkLabel* label;
    gchar* str;
    GError* error;

    // Setup page label
    first_page = gtk_notebook_get_nth_page (priv->notebook, 0);
    gtk_notebook_set_tab_label_text (priv->notebook, first_page, "Channel");

    // Set type label
    str = ti_channel_get_channel_type (priv->channel, &error);
    label = GTK_LABEL (glade_xml_get_widget (priv->glade_xml, "label_channel_type_value"));
    if (error == NULL)
    {
        gtk_label_set_text (label, str);
        g_free (str);
    }
    else
    {
        gtk_label_set_text (label, error->message);
    }

    // Set handle type and number labels
    ti_channel_get_handle (priv->channel, &(priv->self_handle_type), &(priv->self_handle_number), &error);

    label = GTK_LABEL (glade_xml_get_widget (priv->glade_xml, "label_handle_type_value"));
    if (error == NULL)
    {
        str = _get_handle_type_str (priv->self_handle_type);
        gtk_label_set_text (label, str);
        g_free (str);
    }
    else
    {
        gtk_label_set_text (label, error->message);
    }

    priv->label_handle_number = GTK_LABEL (glade_xml_get_widget (priv->glade_xml, "label_handle_number"));
    g_assert (priv->label_handle_number != NULL && GTK_IS_LABEL (priv->label_handle_number));

    priv->label_handle_number_value = GTK_LABEL (glade_xml_get_widget (priv->glade_xml, "label_handle_number_value"));
    g_assert (priv->label_handle_number_value != NULL && GTK_IS_LABEL (priv->label_handle_number_value));

    if (error == NULL)
    {
        if (priv->self_handle_type != TI_CONNECTION_HANDLE_TYPE_CONTACT ||
            ti_preferences_get_handle_display_mode (priv->preferences) ==
                TI_PREFERENCES_HANDLE_DISPLAY_HANDLE)
        {
            str = g_strdup_printf ("%u", priv->self_handle_number);
            gtk_label_set_text (priv->label_handle_number_value, str);
        }
        else
        {
            gtk_label_set_text (priv->label_handle_number, "Name:");
            str = ti_handle_mapper_get_handle_name (priv->handle_mapper, priv->self_handle_type, priv->self_handle_number);
            gtk_label_set_text (priv->label_handle_number_value, str);
        }
        g_free (str);
    }
    else
    {
        gtk_label_set_text (priv->label_handle_number_value, error->message);
    }

    // Interfaces List
    priv->interfaces_list = gtk_list_store_new (1, G_TYPE_STRING);
    _ti_wnd_channel_build_interfaces_treeview (wnd_channel);
    _ti_wnd_channel_fill_interfaces_list (wnd_channel);

    // "close" button
    priv->button_close = glade_xml_get_widget (priv->glade_xml, "button_close");
    g_assert (GTK_IS_BUTTON (priv->button_close));
    g_signal_connect_swapped (priv->button_close, "clicked", G_CALLBACK (_ti_wnd_channel_close_channel), wnd_channel);
}

/**
 * Close Channel
 */
static void
_ti_wnd_channel_close_channel (TIWndChannel* wnd_channel)
{
    TIWndChannelPrivate *priv = TI_WND_CHANNEL_GET_PRIVATE (wnd_channel);
    GError* error;

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

    // Force the window to close.
    _ti_wnd_channel_close_window (wnd_channel);
}

/**
 * Build the GtkTreeView for the interfaces list.
 */
static void
_ti_wnd_channel_build_interfaces_treeview (TIWndChannel* wnd_channel)
{
    TIWndChannelPrivate *priv = TI_WND_CHANNEL_GET_PRIVATE (wnd_channel);
    GtkWidget* treeview_interfaces;
    GtkCellRenderer *renderer;
    GtkTreeViewColumn *column;
    GtkTreeSelection* tree_selection;

    treeview_interfaces = glade_xml_get_widget(priv->glade_xml, "treeview_interfaces");
    gtk_tree_view_set_model (GTK_TREE_VIEW(treeview_interfaces), GTK_TREE_MODEL(priv->interfaces_list));

    renderer = gtk_cell_renderer_text_new ();
    column = gtk_tree_view_column_new_with_attributes ("Interface",
                                                       renderer,
                                                       "text", 0,
                                                       NULL);

    gtk_tree_view_append_column (GTK_TREE_VIEW (treeview_interfaces), column);

    tree_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview_interfaces));
    gtk_tree_selection_set_mode (tree_selection, GTK_SELECTION_NONE);
}

/**
 * Fill Interfaces List
 */
static void
_ti_wnd_channel_fill_interfaces_list (TIWndChannel* wnd_channel)
{
    TIWndChannelPrivate *priv = TI_WND_CHANNEL_GET_PRIVATE (wnd_channel);
    char **str_list;
    char **str_list_ptr;
    GtkTreeIter iter;

    gtk_list_store_clear (priv->interfaces_list);

    str_list = ti_channel_get_interfaces (priv->channel);
    g_return_if_fail (str_list != NULL);

    /* Fill the list. */
    for (str_list_ptr = str_list; *str_list_ptr; str_list_ptr++)
    {
        gtk_list_store_append (priv->interfaces_list, &iter);
        gtk_list_store_set (priv->interfaces_list, &iter, 0, *str_list_ptr, -1);
    }

    g_strfreev (str_list);
}

/**
 * Show
 */
void
ti_wnd_channel_show (TIWndChannel* wnd_channel)
{
    TIWndChannelPrivate *priv = TI_WND_CHANNEL_GET_PRIVATE (wnd_channel);

    gtk_widget_show_all (priv->window);
}

/**
 * On Delete Window
 * Called when the top window receives a "delete-event" signal.
 */
static gboolean
on_delete_window (TIWndChannel* wnd_channel, GdkEvent  *event)
{
    // Just close the window. If the user really wants to close the *telepathy channel*
    // he should click the "Close" *button* instead.
    _ti_wnd_channel_close_window (wnd_channel);

    return TRUE;
}

/**
 * Add Interface Pages
 */
static void
_ti_wnd_channel_add_interface_pages (TIWndChannel* wnd_channel)
{
    TIWndChannelPrivate *priv = TI_WND_CHANNEL_GET_PRIVATE (wnd_channel);
    gchar** interfaces;
    guint i;

    interfaces = ti_channel_get_interfaces (priv->channel);
    g_return_if_fail (interfaces != NULL);

    for (i = 0; interfaces[i] != NULL; i++)
    {
        _ti_wnd_channel_add_interface_page (wnd_channel, interfaces[i]);
    }

    g_strfreev (interfaces);
}

/**
 *Add Interface Page
 */
static void
_ti_wnd_channel_add_interface_page (TIWndChannel* wnd_channel, gchar* interface_name)
{
    TIWndChannelPrivate *priv = TI_WND_CHANNEL_GET_PRIVATE (wnd_channel);
    TIProperties* properties = NULL;

    if (g_str_equal (interface_name, "org.freedesktop.Telepathy.Channel.Interface.Group"))
    {
        priv->page_group = ti_page_channel_group_new (priv->notebook, GTK_WINDOW (priv->window), priv->channel, priv->handle_mapper);
    }
    else if (g_str_equal (interface_name, "org.freedesktop.Telepathy.Properties"))
    {
        properties = ti_properties_new (ti_channel_get_service_name (priv->channel),
                                        ti_channel_get_object_path (priv->channel));

        priv->page_properties = ti_page_properties_new (priv->notebook, properties);
    }
    else
    {
        g_warning ("Unrecognized interface: \"%s\"", interface_name);
    }

    // Clean up
    TI_OBJ_UNREF (properties);
}

/**
 * Get Handle Type Str
 */
static gchar*
_get_handle_type_str (guint handle_type)
{
    switch (handle_type)
    {
        case 0:
            return g_strdup ("0 - CONNECTION_HANDLE_TYPE_NONE");
            break;

        case 1:
            return g_strdup ("1 - CONNECTION_HANDLE_TYPE_CONTACT");
            break;

        case 2:
            return g_strdup ("2 - CONNECTION_HANDLE_TYPE_ROOM");
            break;

        case 3:
            return g_strdup ("3 - CONNECTION_HANDLE_TYPE_LIST");
            break;

        default:
            return g_strdup_printf ("%u - Unknown type", handle_type);
    }
}

/**
 * Window Closed
 */
static void
_ti_wnd_channel_close_window (TIWndChannel* wnd_channel)
{
    TIWndChannelPrivate *priv = TI_WND_CHANNEL_GET_PRIVATE (wnd_channel);

    // Make the connection window destroy us.
    g_signal_emit (wnd_channel, TI_WND_CHANNEL_GET_CLASS(wnd_channel)->close_wnd_id, 0, NULL);
    gtk_widget_hide_all (priv->window);
}

/**
 * Setup Type Interface Page
 * If the channel has an interface for its type (e.g. [...].Type.Text interface for text channels), add it.
 */
static void
_ti_wnd_channel_setup_type_interface_page (TIWndChannel* wnd_channel)
{
    TIWndChannelPrivate *priv = TI_WND_CHANNEL_GET_PRIVATE (wnd_channel);
    gchar* str = NULL;
    GError* error = NULL;

    str = ti_channel_get_channel_type (priv->channel, &error);
    if (error != NULL)
        goto CLEAN_UP;

    if (g_str_equal (str, "org.freedesktop.Telepathy.Channel.Type.Text"))
    {
        priv->page_text = ti_page_channel_text_new (priv->notebook, priv->channel);
    }
    else if (g_str_equal (str, "org.freedesktop.Telepathy.Channel.Type.RoomList"))
    {
        priv->page_room_list = ti_page_room_list_new (priv->notebook, priv->channel, priv->handle_mapper);
    }

    CLEAN_UP:

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

    g_free (str);
}

/**
 * Handle Display Mode Changed
 */
static void
_ti_wnd_channel_handle_display_mode_changed (TIWndChannel* wnd_channel, guint handle_display_mode)
{
    TIWndChannelPrivate* priv = TI_WND_CHANNEL_GET_PRIVATE (wnd_channel);
    gchar* str = NULL;

    if (priv->self_handle_type != TI_CONNECTION_HANDLE_TYPE_CONTACT)
        return;

    if (handle_display_mode == TI_PREFERENCES_HANDLE_DISPLAY_HANDLE)
    {
        gtk_label_set_text (priv->label_handle_number, "Number:");
        str = g_strdup_printf ("%u", priv->self_handle_number);
        gtk_label_set_text (priv->label_handle_number_value, str);
    }
    else
    {
        gtk_label_set_text (priv->label_handle_number, "Name:");
        str = ti_handle_mapper_get_handle_name (priv->handle_mapper, priv->self_handle_type, priv->self_handle_number);
        gtk_label_set_text (priv->label_handle_number_value, str);
    }

    // Clean up
    g_free (str);
}

Generated by  Doxygen 1.6.0   Back to index