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

ti-page-channel-text.c

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

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

struct _TIPageChannelTextClass {
    TIPageClass parent;
};

G_DEFINE_TYPE (TIPageChannelText, ti_page_channel_text, TI_TYPE_PAGE);

/* Function prototypes */
static void _ti_page_channel_text_setup_page (TIPage* page, GladeXML* glade_xml);
static void _ti_page_channel_text_send_message (TIPageChannelText* page_channel_text);
static void _ti_page_channel_text_message_received (TIPageChannelText* page_channel_text,
                                                    guint id, guint timestamp, guint sender, guint type, guint flags, const gchar* text);
static void _ti_page_channel_text_message_sent (TIPageChannelText* page_channel_text,
                                                guint timestamp, guint type, const gchar* text);
static void _ti_page_channel_text_refresh_pending_messages (TIPageChannelText* page_channel_text);
static void _ti_page_channel_text_build_pending_treeview (TIPageChannelText* page_channel_text, GladeXML* glade_xml);
static void _ti_page_channel_text_add_pending_message_to_list (TIPageChannelText* page_channel_text,
                                                               guint id, guint timestamp, guint sender,
                                                               guint type, guint flags, const gchar* text);
static void _ti_page_channel_text_ack_all_pending_messages (TIPageChannelText* page_channel_text);
static GArray* _ti_page_channel_text_build_pending_ids_array (TIPageChannelText* page_channel_text);

/**
 * Instance private data.
 */
00059 struct _TIPageChannelTextPrivate {
    gboolean disposed;

    TIChannel* channel;
    
    GtkTextBuffer* message_log;
    
    GtkListStore* pending_list;
    
    GtkComboBox* combo_send_message_type;
    GtkEntry* entry_send_message_text;
};
typedef struct _TIPageChannelTextPrivate TIPageChannelTextPrivate;

#define TI_PAGE_CHANNEL_TEXT_GET_PRIVATE(object)  (G_TYPE_INSTANCE_GET_PRIVATE ((object), TI_TYPE_PAGE_CHANNEL_TEXT, TIPageChannelTextPrivate))

/**
 * Drop all references to other objects.
 */
static void
ti_page_channel_text_dispose (GObject *object)
{
    TIPageChannelText *page_channel_text = TI_PAGE_CHANNEL_TEXT (object);
    TIPageChannelTextPrivate *priv = TI_PAGE_CHANNEL_TEXT_GET_PRIVATE (page_channel_text);

    if (priv->disposed)
    {
        return;
    }
    else
    {
        priv->disposed = TRUE;
    }

    if (priv->channel != NULL)
    {
        g_object_unref (priv->channel);
        priv->channel = NULL;
    }

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

/**
 * Class initialization.
 */
static void
ti_page_channel_text_class_init (TIPageChannelTextClass *ti_page_channel_text_class)
{
      GObjectClass *gobject_class = G_OBJECT_CLASS (ti_page_channel_text_class);
    TIPageClass* page_class = TI_PAGE_CLASS (ti_page_channel_text_class);

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

    page_class->setup_page = _ti_page_channel_text_setup_page;
            
      /* Add private */
      g_type_class_add_private (ti_page_channel_text_class, sizeof (TIPageChannelTextPrivate));
}

/**
 * Instance initialization.
 */
static void
ti_page_channel_text_init (TIPageChannelText *ti_page_channel_text)
{
    TIPageChannelTextPrivate *priv = TI_PAGE_CHANNEL_TEXT_GET_PRIVATE (ti_page_channel_text);

    priv->disposed = FALSE;
    priv->channel = NULL;
}

/**
 * Returns a new instance.
 */
TIPageChannelText*
ti_page_channel_text_new (GtkNotebook* parent_notebook, TIChannel* channel) 
{
    TIPageChannelText* page_channel_text = NULL;
    TIPageChannelTextPrivate* priv = NULL;

    g_assert (channel != NULL);

      page_channel_text = g_object_new (TI_TYPE_PAGE_CHANNEL_TEXT, NULL);

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

    _ti_page_new ((TIPage**)&page_channel_text, parent_notebook, "page-channel-text.xml");
 

    return page_channel_text;
}

/**
 * Setup Page - Helper Function
 */
static void
_ti_page_channel_text_setup_page (TIPage* page, GladeXML* glade_xml)
{
    TIPageChannelText* page_channel_text = TI_PAGE_CHANNEL_TEXT (page);
    TIPageChannelTextPrivate *priv = TI_PAGE_CHANNEL_TEXT_GET_PRIVATE (page_channel_text);
    GtkWidget* widget;
    
    // Connect to TIChannel signals
    g_signal_connect_swapped (priv->channel, "received", G_CALLBACK (_ti_page_channel_text_message_received), page_channel_text);
    g_signal_connect_swapped (priv->channel, "sent", G_CALLBACK (_ti_page_channel_text_message_sent), page_channel_text);

    // Pending messages List
    priv->pending_list = gtk_list_store_new (6, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
    _ti_page_channel_text_build_pending_treeview (page_channel_text, glade_xml);
    _ti_page_channel_text_refresh_pending_messages (page_channel_text);

    // "Acknowledge All" button in "Pending messages" frame.
    widget = glade_xml_get_widget (glade_xml, "button_pending_messages_ack_all");
    g_assert (GTK_IS_BUTTON (widget));
    g_signal_connect_swapped (widget, "clicked", G_CALLBACK (_ti_page_channel_text_ack_all_pending_messages), page_channel_text);

    // "Refresh" button in "Pending messages" frame.
    widget = glade_xml_get_widget (glade_xml, "button_pending_messages_refresh");
    g_assert (GTK_IS_BUTTON (widget));
    g_signal_connect_swapped (widget, "clicked", G_CALLBACK (_ti_page_channel_text_refresh_pending_messages), page_channel_text);
    
    // Message types combobox in "Send message" frame.
    priv->combo_send_message_type = GTK_COMBO_BOX (glade_xml_get_widget (glade_xml, "combo_send_message_type"));
    g_assert (GTK_IS_COMBO_BOX (priv->combo_send_message_type));

    // Text entry in "Send message" frame.
    priv->entry_send_message_text = GTK_ENTRY (glade_xml_get_widget (glade_xml, "entry_send_message_text"));
    g_assert (GTK_IS_ENTRY (priv->entry_send_message_text));
    
    // "Send" button in "Send message" frame.
    widget = glade_xml_get_widget (glade_xml, "button_send_message");
    g_assert (GTK_IS_BUTTON (widget));
    g_signal_connect_swapped (widget, "clicked", G_CALLBACK (_ti_page_channel_text_send_message), page_channel_text);
    
    // Message Log
    widget = glade_xml_get_widget (glade_xml, "textview_messages_log");
    g_assert (GTK_IS_TEXT_VIEW (widget));
    priv->message_log = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget));
}

/**
 * Send Message
 */
static void
_ti_page_channel_text_send_message (TIPageChannelText* page_channel_text)
{
    TIPageChannelTextPrivate *priv = TI_PAGE_CHANNEL_TEXT_GET_PRIVATE (page_channel_text);
    GError* error;
    guint type;
    const gchar* text;

    type = gtk_combo_box_get_active (priv->combo_send_message_type);
    g_return_if_fail (type >= 0 && type <= 3);
    
    text = gtk_entry_get_text (priv->entry_send_message_text);
    
    ti_channel_typetext_send (priv->channel, type, text, &error);
    if (error != NULL)
    {
        // TODO: Display error or something.
        g_error_free (error);
    }
}

/**
 * Message Received
 */
static void
_ti_page_channel_text_message_received (TIPageChannelText* page_channel_text,
                                        guint id, guint timestamp, guint sender, guint type, guint flags, const gchar* text)
{
    TIPageChannelTextPrivate *priv = TI_PAGE_CHANNEL_TEXT_GET_PRIVATE (page_channel_text);
    GtkTextIter iter;
    gchar* log_text;

    g_debug ("Page Channel Text - Received");

    log_text = g_strdup_printf ("<%u|received|id %u|sender %u|type %u|flags %u> \"%s\"\n", timestamp, id, sender, type, flags, text);
    
    gtk_text_buffer_get_end_iter (priv->message_log, &iter);
    gtk_text_buffer_insert (priv->message_log, &iter, log_text, -1);
    
    g_free (log_text);
    
    _ti_page_channel_text_refresh_pending_messages (page_channel_text);
}

/**
 * Message Sent
 */
static void
_ti_page_channel_text_message_sent (TIPageChannelText* page_channel_text,
                                    guint timestamp, guint type, const gchar* text)
{
    TIPageChannelTextPrivate *priv = TI_PAGE_CHANNEL_TEXT_GET_PRIVATE (page_channel_text);
    GtkTextIter iter;
    gchar* log_text;

    g_debug ("Page Channel Text - Sent");
    
    log_text = g_strdup_printf ("<%u|sent|type %u|> \"%s\"\n", timestamp, type, text);
    
    gtk_text_buffer_get_end_iter (priv->message_log, &iter);
    gtk_text_buffer_insert (priv->message_log, &iter, log_text, -1);
    
    g_free (log_text);
}

/**
 * Refresh Pending Messages
 */
static void
_ti_page_channel_text_refresh_pending_messages (TIPageChannelText* page_channel_text)
{
    TIPageChannelTextPrivate *priv = TI_PAGE_CHANNEL_TEXT_GET_PRIVATE (page_channel_text);
    GPtrArray* pending_messages;
    GValueArray* message;
    guint i;
    GError* error;

    // Pending message fields
    guint id;
    guint timestamp;
    guint sender;
    guint type;
    guint flags;
    const gchar* text;

    gtk_list_store_clear (priv->pending_list);

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

    for (i = 0; i < pending_messages->len; i++)
    {
        message = g_ptr_array_index (pending_messages, i);

        id        = g_value_get_uint   (&(message->values[0]));
        timestamp = g_value_get_uint   (&(message->values[1]));
        sender    = g_value_get_uint   (&(message->values[2]));
        type      = g_value_get_uint   (&(message->values[3]));
        flags     = g_value_get_uint   (&(message->values[4]));
        text      = g_value_get_string (&(message->values[5]));
        
        _ti_page_channel_text_add_pending_message_to_list (page_channel_text, id, timestamp, sender, type, flags, text);

        g_value_array_free (message);
    }

    g_ptr_array_free (pending_messages, TRUE);
}

/**
 * Build Pending Treeview
 */
static void
_ti_page_channel_text_build_pending_treeview (TIPageChannelText*  page_channel_text, GladeXML* glade_xml)
{
    TIPageChannelTextPrivate* priv = TI_PAGE_CHANNEL_TEXT_GET_PRIVATE (page_channel_text);
    GtkWidget* treeview_pending;
    GtkCellRenderer *renderer;
    GtkTreeViewColumn *column;
    GtkTreeSelection* tree_selection;

    treeview_pending = glade_xml_get_widget(glade_xml, "treeview_pending_messages");
    gtk_tree_view_set_model (GTK_TREE_VIEW(treeview_pending), GTK_TREE_MODEL(priv->pending_list));

    renderer = gtk_cell_renderer_text_new ();
    
    /* ID column */
    column = gtk_tree_view_column_new_with_attributes ("ID",
                                                       renderer,
                                                       "text", 0,
                                                       NULL);
    gtk_tree_view_append_column (GTK_TREE_VIEW (treeview_pending), column);
    
    /* Timestamp column */
    column = gtk_tree_view_column_new_with_attributes ("Timestamp",
                                                       renderer,
                                                       "text", 1,
                                                       NULL);
    gtk_tree_view_append_column (GTK_TREE_VIEW (treeview_pending), column);
    
    /* Sender column */
    column = gtk_tree_view_column_new_with_attributes ("Sender",
                                                       renderer,
                                                       "text", 2,
                                                       NULL);
    gtk_tree_view_append_column (GTK_TREE_VIEW (treeview_pending), column);
    
    /* Type column */
    column = gtk_tree_view_column_new_with_attributes ("Type",
                                                       renderer,
                                                       "text", 3,
                                                       NULL);
    gtk_tree_view_append_column (GTK_TREE_VIEW (treeview_pending), column);
    
    /* Flags column */
    column = gtk_tree_view_column_new_with_attributes ("Flags",
                                                       renderer,
                                                       "text", 4,
                                                       NULL);
    gtk_tree_view_append_column (GTK_TREE_VIEW (treeview_pending), column);
    
    /* Text column */
    column = gtk_tree_view_column_new_with_attributes ("Text",
                                                       renderer,
                                                       "text", 5,
                                                       NULL);
    gtk_tree_view_append_column (GTK_TREE_VIEW (treeview_pending), column);

    tree_selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview_pending));
    gtk_tree_selection_set_mode (tree_selection, GTK_SELECTION_SINGLE);
}

/**
 * Add Pending Message To List
 */
static void
_ti_page_channel_text_add_pending_message_to_list (TIPageChannelText* page_channel_text,
                                                   guint id,
                                                   guint timestamp,
                                                   guint sender,
                                                   guint type,
                                                   guint flags,
                                                   const gchar* text)
{
    TIPageChannelTextPrivate* priv = TI_PAGE_CHANNEL_TEXT_GET_PRIVATE (page_channel_text);
    GtkTreeIter iter;
    gchar* id_str;
    gchar* timestamp_str;
    gchar* sender_str;
    gchar* type_str;
    gchar* flags_str;

    id_str        = g_strdup_printf ("%u", id);
    timestamp_str = g_strdup_printf ("%u", timestamp);
    sender_str    = g_strdup_printf ("%u", sender);
    type_str      = g_strdup_printf ("%u", type);
    flags_str     = g_strdup_printf ("%u", flags);

    gtk_list_store_append (priv->pending_list, &iter);
    gtk_list_store_set (priv->pending_list, &iter,
                        0, id_str,
                        1, timestamp_str,
                        2, sender_str,
                        3, type_str,
                        4, flags_str,
                        5, text,
                        -1);

    g_free (id_str);
    g_free (timestamp_str);
    g_free (sender_str);
    g_free (type_str);
    g_free (flags_str);
}

/**
 * Acknowledge All Pending Messages
 */
static void
_ti_page_channel_text_ack_all_pending_messages (TIPageChannelText* page_channel_text)
{
    TIPageChannelTextPrivate* priv = TI_PAGE_CHANNEL_TEXT_GET_PRIVATE (page_channel_text);
    GError* error;
    GArray* ids;
    
    ids = _ti_page_channel_text_build_pending_ids_array (page_channel_text);
    g_return_if_fail (ids != NULL);
    
    ti_channel_typetext_acknowledge_pending_messages (priv->channel, ids, &error);
    if (error != NULL)
    {
        // TODO: Display a message or something.
    }
    
    g_array_free (ids, TRUE);
    
    _ti_page_channel_text_refresh_pending_messages (page_channel_text);
}

static GArray*
_ti_page_channel_text_build_pending_ids_array (TIPageChannelText* page_channel_text)
{
    TIPageChannelTextPrivate* priv = TI_PAGE_CHANNEL_TEXT_GET_PRIVATE (page_channel_text);
    GArray* ids;
    GtkTreeIter iter;
    GValue value = {0, };
    GtkTreeModel* tree_model = GTK_TREE_MODEL (priv->pending_list);
    guint id;
    gboolean ok;
    int result;

    ids = g_array_new (FALSE, FALSE, sizeof (guint));

    ok = gtk_tree_model_get_iter_first (tree_model, &iter);
    if (!ok)
    {
        g_array_free (ids, TRUE);
        return NULL;
    }

    ok = TRUE;
    while (ok) {
        gtk_tree_model_get_value (tree_model, &iter, 0, &value); // ID
        g_assert (G_VALUE_HOLDS_STRING(&value));
        g_assert (strlen (g_value_get_string(&value)) > 0);

        result = sscanf (g_value_get_string(&value), "%u", &id);
        g_assert (result == 1);
        
        g_array_append_val (ids, id);
        
        g_value_unset (&value);
        
        ok = gtk_tree_model_iter_next (tree_model, &iter);
    }

    return ids;
}

Generated by  Doxygen 1.6.0   Back to index