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

ti-page-channel-group.c

/*
 * Telapathy Inspector - A Telepathy client which exposes Telepathy interfaces.
 *                       Meant to inspect and/or test connection managers.
 * 
 * ti-page-channel-group.c:
 * A GtkNotebook page exposing org.freedesktop.Telepathy.Channel.Interface.Group
 * 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-group.h"
#include "ti-page-priv.h"
#include "ti-channel.h"
#include "ti-constants.h"
#include "ti-dlg-get-text.h"
#include "ti-dlg-add-members.h"
#include "ti-config.h"
#include "ti-preferences.h"
#include "ti-util.h"

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

enum {
    TI_COLUMN_MEMBERS_LIST_HANDLE = 0,
    TI_COLUMN_MEMBERS_LIST_NAME,
    TI_COLUMN_MEMBERS_LIST_STATUS,
    TI_COLUMN_MEMBERS_LIST_N_COLUMNS
};

#define TI_GROUP_MEMBER_STATUS_REGULAR        "member"
#define TI_GROUP_MEMBER_STATUS_LOCAL_PENDING  "local pending"
#define TI_GROUP_MEMBER_STATUS_REMOTE_PENDING "remote pending"

struct _TIPageChannelGroupClass {
    TIPageClass parent;
};

G_DEFINE_TYPE (TIPageChannelGroup, ti_page_channel_group, TI_TYPE_PAGE);

/* Function prototypes */
static void _ti_page_channel_group_setup_page (TIPage* page, GladeXML* glade_xml);
static void _ti_page_channel_group_build_members_treeview (TIPageChannelGroup* page_channel_group, GladeXML* glade_xml);
static void _ti_page_channel_group_fill_members_list (TIPageChannelGroup* page_channel_group);
static void _ti_page_channel_group_append_members_to_list (TIPageChannelGroup* page_channel_group, GArray* handles, const gchar* status);
static void _ti_page_channel_group_setup_group_flags (TIPageChannelGroup* page_channel_group, GladeXML* glade_xml);
static void _ti_page_channel_group_remove_selected_members (TIPageChannelGroup* page_channel_group);
static void _ti_page_channel_group_add_members (TIPageChannelGroup* page_channel_group);
static void _ti_page_channel_group_members_changed (TIPageChannelGroup* page_channel_group,
                                                    const gchar* message,
                                                    GArray* added, GArray* removed,
                                                    GArray* local_pending, GArray* remote_pending,
                                                    guint actor, guint reason);
static void _ti_page_channel_group_log_members_changed (TIPageChannelGroup* page_channel_group,
                                                        const gchar* message,
                                                        GArray* added, GArray* removed,
                                                        GArray* local_pending, GArray* remote_pending,
                                                        guint actor, guint reason);
static void _ti_page_channel_group_remove_members (TIPageChannelGroup* page_channel_group, GArray* removed_handles);
static void _ti_page_channel_group_remove_member (TIPageChannelGroup* page_channel_group, guint handle);
static void _ti_page_channel_group_update_button_remove_sensitivity (TIPageChannelGroup* page_channel_group);
static void _ti_page_channel_group_clear_log (TIPageChannelGroup* page_channel_group);
static void _ti_page_channel_group_group_flags_changed (TIPageChannelGroup* page_channel_group, guint added, guint removed);
static void _ti_page_channel_group_log_group_flags_changed (TIPageChannelGroup* page_channel_group, guint added, guint removed);
static void _ti_page_channel_group_refresh_group_flags_checkboxes (TIPageChannelGroup* page_channel_group);
static void _ti_page_channel_group_update_selection_permissions (TIPageChannelGroup* page_channel_group);
static void _group_flags_to_string (GString* text, guint flags);
static void _ti_page_channel_group_handle_display_mode_changed (TIPageChannelGroup* page_channel_group, guint handle_display_mode);
static gboolean _ti_page_channel_get_contact_row (TIPageChannelGroup* page_channel_group, guint contact_handle, GtkTreeIter* iter);

/**
 * Instance private data.
 */
00090 struct _TIPageChannelGroupPrivate {
    TIChannel* channel;

    TIPreferences* preferences;
    TIHandleMapper* handle_mapper;

    guint group_flags;

    TIDlgAddMembers* dialog_add_members;
    TIDlgGetText* dialog_get_text;

    GtkListStore* members_list;
    GtkTreeView* members_tree_view;
    GtkTreeSelection* members_selection;

    GtkWidget* checkbutton_can_add;
    GtkWidget* checkbutton_can_remove;
    GtkWidget* checkbutton_can_rescind;
    GtkWidget* checkbutton_message_add;
    GtkWidget* checkbutton_message_remove;
    GtkWidget* checkbutton_message_accept;
    GtkWidget* checkbutton_message_reject;
    GtkWidget* checkbutton_message_rescind;
    GtkWidget* checkbutton_channel_specific_handles;

    GtkButton* button_remove_members;
    GtkButton* button_add_members;

    GtkTextBuffer* textbuffer_event_log;
};
typedef struct _TIPageChannelGroupPrivate TIPageChannelGroupPrivate;

#define TI_PAGE_CHANNEL_GROUP_GET_PRIVATE(object)  (G_TYPE_INSTANCE_GET_PRIVATE ((object), TI_TYPE_PAGE_CHANNEL_GROUP, TIPageChannelGroupPrivate))

/**
 * Drop all references to other objects.
 */
static void
ti_page_channel_group_dispose (GObject *object)
{
    TIPageChannelGroup *page_channel_group = TI_PAGE_CHANNEL_GROUP (object);
    TIPageChannelGroupPrivate *priv = TI_PAGE_CHANNEL_GROUP_GET_PRIVATE (page_channel_group);

    if (priv->channel != NULL)
    {
        g_signal_handlers_disconnect_by_func(priv->channel,
                                             G_CALLBACK (_ti_page_channel_group_members_changed),
                                             page_channel_group);

        g_signal_handlers_disconnect_by_func(priv->channel,
                                             G_CALLBACK (_ti_page_channel_group_group_flags_changed),
                                             page_channel_group);

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

    if (priv->preferences != NULL)
    {
        g_signal_handlers_disconnect_by_func(priv->preferences,
                                             G_CALLBACK (_ti_page_channel_group_handle_display_mode_changed),
                                             page_channel_group);

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

    TI_OBJ_UNREF (priv->handle_mapper);
    TI_OBJ_UNREF (priv->dialog_add_members);
    TI_OBJ_UNREF (priv->dialog_get_text);
    TI_OBJ_UNREF (priv->members_list);

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

/**
 * Class initialization.
 */
static void
ti_page_channel_group_class_init (TIPageChannelGroupClass *ti_page_channel_group_class)
{
    GObjectClass *gobject_class = G_OBJECT_CLASS (ti_page_channel_group_class);
    TIPageClass* page_class = TI_PAGE_CLASS (ti_page_channel_group_class);

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

    page_class->setup_page = _ti_page_channel_group_setup_page;

    /* Add private */
    g_type_class_add_private (ti_page_channel_group_class, sizeof (TIPageChannelGroupPrivate));
}

/**
 * Instance initialization.
 */
static void
ti_page_channel_group_init (TIPageChannelGroup *ti_page_channel_group)
{
    TIPageChannelGroupPrivate *priv = TI_PAGE_CHANNEL_GROUP_GET_PRIVATE (ti_page_channel_group);

    priv->channel = NULL;
    priv->preferences = ti_preferences_new ();
    priv->handle_mapper = NULL;
    priv->dialog_add_members = NULL;
    priv->dialog_get_text = NULL;
    priv->members_list = NULL;
}

/**
 * Returns a new instance.
 */
TIPageChannelGroup*
ti_page_channel_group_new (GtkNotebook* parent_notebook, GtkWindow* parent_window, TIChannel* channel, TIHandleMapper* handle_mapper) 
{
    TIPageChannelGroup* page_channel_group = NULL;
    TIPageChannelGroupPrivate *priv = NULL;

    g_assert (channel != NULL);

      page_channel_group = g_object_new (TI_TYPE_PAGE_CHANNEL_GROUP, NULL);
    priv = TI_PAGE_CHANNEL_GROUP_GET_PRIVATE (page_channel_group);
    
    priv->channel = channel;
    g_object_ref (channel);

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

    g_signal_connect_swapped (channel, "members-changed", G_CALLBACK (_ti_page_channel_group_members_changed), page_channel_group);
    g_signal_connect_swapped (channel, "group-flags-changed", G_CALLBACK (_ti_page_channel_group_group_flags_changed), page_channel_group);

    g_signal_connect_swapped (priv->preferences, "handle-display-mode-changed",
                              G_CALLBACK (_ti_page_channel_group_handle_display_mode_changed), page_channel_group);

    priv->dialog_add_members = ti_dlg_add_members_new (parent_window, handle_mapper);
    if (priv->dialog_add_members == NULL)
    {
        g_object_unref (page_channel_group);
        page_channel_group = NULL;
        goto CLEAN_UP;
    }

    priv->dialog_get_text = ti_dlg_get_text_new (parent_window, "Enter message:");
    if (priv->dialog_get_text == NULL)
    {
        g_object_unref (page_channel_group);
        page_channel_group = NULL;
        goto CLEAN_UP;
    }

    _ti_page_new ((TIPage**)&page_channel_group, parent_notebook, "page-channel-group.xml");

    CLEAN_UP:
    return page_channel_group;
}

/**
 * Setup Page - Helper Function
 */
static void
_ti_page_channel_group_setup_page (TIPage* page, GladeXML* glade_xml)
{
    TIPageChannelGroup* page_channel_group = TI_PAGE_CHANNEL_GROUP (page);
    TIPageChannelGroupPrivate *priv = TI_PAGE_CHANNEL_GROUP_GET_PRIVATE (page_channel_group);
    gboolean can_add;
    GtkWidget* widget;

    // Group Flags
    _ti_page_channel_group_setup_group_flags (page_channel_group, glade_xml);
    
    // Members List
    _ti_page_channel_group_build_members_treeview (page_channel_group, glade_xml);
    _ti_page_channel_group_fill_members_list (page_channel_group);
    
    // Button Remove Members
    priv->button_remove_members = GTK_BUTTON (glade_xml_get_widget(glade_xml, "button_remove_members"));
    g_assert (GTK_IS_BUTTON (priv->button_remove_members));
    g_signal_connect_swapped (priv->button_remove_members, "clicked", G_CALLBACK (_ti_page_channel_group_remove_selected_members), page_channel_group);
    
    // Button Add Members
    priv->button_add_members = GTK_BUTTON (glade_xml_get_widget(glade_xml, "button_add_members"));
    g_assert (GTK_IS_BUTTON (priv->button_add_members));
    g_signal_connect_swapped (priv->button_add_members, "clicked", G_CALLBACK (_ti_page_channel_group_add_members), page_channel_group);

    can_add = (priv->group_flags & TI_CHANNEL_GROUP_FLAG_CAN_ADD) != 0;
    gtk_widget_set_sensitive (GTK_WIDGET (priv->button_remove_members), can_add);

    // Button Refresh Members
    widget = glade_xml_get_widget(glade_xml, "button_refresh_members");
    g_assert (GTK_IS_BUTTON (widget));
    g_signal_connect_swapped (GTK_BUTTON (widget), "clicked", G_CALLBACK (_ti_page_channel_group_fill_members_list), page_channel_group);

    // TextView Event Log
    widget = glade_xml_get_widget(glade_xml, "textview_event_log");
    g_assert (GTK_IS_TEXT_VIEW (widget));
    priv->textbuffer_event_log = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget));

    // Button Clear Event Log
    widget = glade_xml_get_widget(glade_xml, "button_event_log_clear");
    g_assert (GTK_IS_BUTTON (widget));
    g_signal_connect_swapped (GTK_BUTTON (widget), "clicked", G_CALLBACK (_ti_page_channel_group_clear_log), page_channel_group);
}

/**
 * Build Members Treeview
 */
static void
_ti_page_channel_group_build_members_treeview (TIPageChannelGroup* page_channel_group, GladeXML* glade_xml)
{
    TIPageChannelGroupPrivate *priv = TI_PAGE_CHANNEL_GROUP_GET_PRIVATE (page_channel_group);
    GtkCellRenderer *renderer;
    GtkTreeViewColumn *column;

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

    priv->members_list = gtk_list_store_new (3, G_TYPE_UINT /*handle*/, G_TYPE_STRING /*name*/, G_TYPE_STRING /*status*/);
    gtk_tree_view_set_model (priv->members_tree_view, GTK_TREE_MODEL (priv->members_list));

    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", 0,
                                                           NULL);
        gtk_tree_view_append_column (priv->members_tree_view, column);
    }
    else
    {
        column = gtk_tree_view_column_new_with_attributes ("Name",
                                                           renderer,
                                                           "text", 1,
                                                           NULL);
        gtk_tree_view_append_column (priv->members_tree_view, column);
    }

    // Status column. Displays something like "local pending", "remote pending" and "regular member".
    column = gtk_tree_view_column_new_with_attributes ("Status",
                                                       renderer,
                                                       "text", 2,
                                                       NULL);
    gtk_tree_view_append_column (priv->members_tree_view, column);

    priv->members_selection = gtk_tree_view_get_selection (priv->members_tree_view);

    g_signal_connect_swapped (priv->members_selection, "changed",
                              G_CALLBACK (_ti_page_channel_group_update_button_remove_sensitivity),
                              page_channel_group);

    gtk_tree_selection_set_mode (priv->members_selection, GTK_SELECTION_MULTIPLE);
}

/**
 * Fill Members List
 */
static void
_ti_page_channel_group_fill_members_list (TIPageChannelGroup* page_channel_group)
{
    TIPageChannelGroupPrivate *priv = TI_PAGE_CHANNEL_GROUP_GET_PRIVATE (page_channel_group);
    GArray* handles = NULL;
    GError* error = NULL;

    gtk_list_store_clear (priv->members_list);

    // Get Regular Members

    handles = ti_channel_igroup_get_members (priv->channel, &error);
    if (error != NULL)
    {
        goto CLEAN_UP;
    }

    _ti_page_channel_group_append_members_to_list (page_channel_group, handles, TI_GROUP_MEMBER_STATUS_REGULAR);
    g_array_free (handles, TRUE);
    handles = NULL;

    // Get Local Pending Members

    handles = ti_channel_igroup_get_local_pending_members (priv->channel, &error);
    if (error != NULL)
    {
        goto CLEAN_UP;
    }

    _ti_page_channel_group_append_members_to_list (page_channel_group, handles, TI_GROUP_MEMBER_STATUS_LOCAL_PENDING);
    g_array_free (handles, TRUE);
    handles = NULL;

    // Get Remote Pending Members

    handles = ti_channel_igroup_get_remote_pending_members (priv->channel, &error);
    if (error != NULL)
    {
        goto CLEAN_UP;
    }

    _ti_page_channel_group_append_members_to_list (page_channel_group, handles, TI_GROUP_MEMBER_STATUS_REMOTE_PENDING);
    g_array_free (handles, TRUE);
    handles = NULL;

    CLEAN_UP:
    if (handles != NULL)
    {
        g_array_free (handles, TRUE);
    }
}

/**
 * Append Members To List
 */
static void
_ti_page_channel_group_append_members_to_list (TIPageChannelGroup* page_channel_group, GArray* handles, const gchar* status)
{
    TIPageChannelGroupPrivate *priv = TI_PAGE_CHANNEL_GROUP_GET_PRIVATE (page_channel_group);
    GtkTreeIter iter;
    guint i;
    guint handle;
    gchar* name;

    /* Fill the list. */
    for (i = 0; i < handles->len; i++)
    {
        handle = g_array_index (handles, guint, i);

        name = ti_handle_mapper_get_contact_handle_name (priv->handle_mapper, handle);
        if (name == NULL)
        {
            name = g_strdup_printf ("%u", handle);
        }

        // If there's not already a row for that contact, we create one.
        if (!_ti_page_channel_get_contact_row (page_channel_group, handle, &iter))
        {
            gtk_list_store_append (priv->members_list, &iter);
        }

        gtk_list_store_set (priv->members_list, &iter,
                            TI_COLUMN_MEMBERS_LIST_HANDLE, handle,
                            TI_COLUMN_MEMBERS_LIST_NAME, name,
                            TI_COLUMN_MEMBERS_LIST_STATUS, status,
                            -1);

        g_free (name);
    }
}

/**
 * Setup Group Flags
 */
static void
_ti_page_channel_group_setup_group_flags (TIPageChannelGroup* page_channel_group, GladeXML* glade_xml)
{
    TIPageChannelGroupPrivate *priv = TI_PAGE_CHANNEL_GROUP_GET_PRIVATE (page_channel_group);
    GError* error;

    /*** Get widgets from glade object. ***/

    priv->checkbutton_can_add = glade_xml_get_widget(glade_xml, "checkbutton_can_add");
    g_assert (GTK_IS_CHECK_BUTTON (priv->checkbutton_can_add));
    
    priv->checkbutton_can_remove = glade_xml_get_widget(glade_xml, "checkbutton_can_remove");
    g_assert (GTK_IS_CHECK_BUTTON (priv->checkbutton_can_remove));

    priv->checkbutton_can_rescind = glade_xml_get_widget(glade_xml, "checkbutton_can_rescind");
    g_assert (GTK_IS_CHECK_BUTTON (priv->checkbutton_can_rescind));

    priv->checkbutton_message_add = glade_xml_get_widget(glade_xml, "checkbutton_message_add");
    g_assert (GTK_IS_CHECK_BUTTON (priv->checkbutton_message_add));

    priv->checkbutton_message_remove = glade_xml_get_widget(glade_xml, "checkbutton_message_remove");
    g_assert (GTK_IS_CHECK_BUTTON (priv->checkbutton_message_remove));

    priv->checkbutton_message_accept = glade_xml_get_widget(glade_xml, "checkbutton_message_accept");
    g_assert (GTK_IS_CHECK_BUTTON (priv->checkbutton_message_accept));

    priv->checkbutton_message_reject = glade_xml_get_widget(glade_xml, "checkbutton_message_reject");
    g_assert (GTK_IS_CHECK_BUTTON (priv->checkbutton_message_reject));

    priv->checkbutton_message_rescind = glade_xml_get_widget(glade_xml, "checkbutton_message_rescind");
    g_assert (GTK_IS_CHECK_BUTTON (priv->checkbutton_message_rescind));

    priv->checkbutton_channel_specific_handles = glade_xml_get_widget(glade_xml, "checkbutton_channel_specific_handles");
    g_assert (GTK_IS_CHECK_BUTTON (priv->checkbutton_channel_specific_handles));

    /*** Set checkbutton states ***/
    
    priv->group_flags = ti_channel_igroup_get_group_flags (priv->channel, &error);
    if (error != NULL)
    {
        // TODO: Display a message or something.
        g_error_free (error);
        return;
    }
    
    _ti_page_channel_group_refresh_group_flags_checkboxes (page_channel_group);
}

/**
 * Remove Selected Members
 */
static void
_ti_page_channel_group_remove_selected_members (TIPageChannelGroup* page_channel_group)
{
    TIPageChannelGroupPrivate *priv = TI_PAGE_CHANNEL_GROUP_GET_PRIVATE (page_channel_group);
    GError* error = NULL;
    GArray* members = NULL;
    gchar* message = NULL;
    gboolean ok;

    members = ti_get_selected_elements (priv->members_selection, TI_COLUMN_MEMBERS_LIST_HANDLE, G_TYPE_UINT);
    g_assert (members != NULL);

    if ((priv->group_flags & TI_CHANNEL_GROUP_FLAG_MESSAGE_REMOVE) != 0)
    {
        ok = ti_dlg_get_text_run (priv->dialog_get_text, &message);
        if (!ok)
            goto CLEAN_UP;
    }

    ti_channel_igroup_remove_members (priv->channel, members, message, &error);
    if (error != NULL)
    {
        // TODO: Display a message or something.
        g_error_free (error);
    }
    
    CLEAN_UP:
    g_free (message);
    g_array_free (members, TRUE);
}

/**
 * Add Members
 */
static void
_ti_page_channel_group_add_members (TIPageChannelGroup* page_channel_group)
{
    TIPageChannelGroupPrivate *priv = TI_PAGE_CHANNEL_GROUP_GET_PRIVATE (page_channel_group);
    gboolean ok;
    GArray* handles = NULL;
    GError* error = NULL;
    gchar* message = NULL;
    GArray* selected_handles = NULL;

    selected_handles = ti_get_selected_elements (priv->members_selection, TI_COLUMN_MEMBERS_LIST_HANDLE, G_TYPE_UINT);

    ok = ti_dlg_add_members_run (priv->dialog_add_members, selected_handles, &handles, &message);
    if (!ok)
    {
        goto CLEAN_UP;
    }

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

    CLEAN_UP:
    g_free (message);
    g_array_free (selected_handles, TRUE);

    if (handles != NULL)
        g_array_free (handles, TRUE);

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

/**
 * Members Changed
 */
static void
_ti_page_channel_group_members_changed (TIPageChannelGroup* page_channel_group,
                                        const gchar* message,
                                        GArray* added, GArray* removed,
                                        GArray* local_pending, GArray* remote_pending,
                                        guint actor, guint reason)
{
    g_assert (added != NULL);
    g_assert (local_pending != NULL);
    g_assert (remote_pending != NULL);

    _ti_page_channel_group_log_members_changed (page_channel_group, message, added, removed, local_pending, remote_pending, actor, reason);

    _ti_page_channel_group_append_members_to_list (page_channel_group, added, TI_GROUP_MEMBER_STATUS_REGULAR);
    _ti_page_channel_group_append_members_to_list (page_channel_group, local_pending, TI_GROUP_MEMBER_STATUS_LOCAL_PENDING);
    _ti_page_channel_group_append_members_to_list (page_channel_group, remote_pending, TI_GROUP_MEMBER_STATUS_REMOTE_PENDING);

    _ti_page_channel_group_remove_members (page_channel_group, removed);
}

/**
 * Remove Members
 */
static void
_ti_page_channel_group_remove_members (TIPageChannelGroup* page_channel_group, GArray* removed_handles)
{
    guint i;
    guint handle;

    for (i = 0; i < removed_handles->len; i++)
    {
        handle = g_array_index (removed_handles, guint, i);
        _ti_page_channel_group_remove_member (page_channel_group, handle);
    }
}

/**
 * Remove Member
 */
static void
_ti_page_channel_group_remove_member (TIPageChannelGroup* page_channel_group, guint handle)
{
    TIPageChannelGroupPrivate *priv = TI_PAGE_CHANNEL_GROUP_GET_PRIVATE (page_channel_group);
    gboolean ok;
    GtkTreeIter iter;
    gboolean removed = FALSE;
    guint member_handle;

    ok = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->members_list), &iter);
    if (!ok)
    {
        return; // The list is empty.
    }

    while (ok && !removed)
    {
        gtk_tree_model_get (GTK_TREE_MODEL (priv->members_list), &iter,
                            TI_COLUMN_MEMBERS_LIST_HANDLE, &member_handle,
                            -1);

        if (member_handle == handle)
        {
            gtk_list_store_remove (priv->members_list, &iter);
            removed = TRUE;
        }
        else
        {
            ok = gtk_tree_model_iter_next  (GTK_TREE_MODEL (priv->members_list), &iter);
        }
    }
}

/**
 * Update Button Remove Sensitivity
 */
static void
_ti_page_channel_group_update_button_remove_sensitivity (TIPageChannelGroup* page_channel_group)
{
    TIPageChannelGroupPrivate *priv = TI_PAGE_CHANNEL_GROUP_GET_PRIVATE (page_channel_group);
    gint selection_count;

    selection_count = gtk_tree_selection_count_selected_rows (priv->members_selection);

    gtk_widget_set_sensitive (GTK_WIDGET (priv->button_remove_members), selection_count > 0);
}

/**
 * Log Members Changed
 */
static void
_ti_page_channel_group_log_members_changed (TIPageChannelGroup* page_channel_group,
                                            const gchar* message,
                                            GArray* added, GArray* removed,
                                            GArray* local_pending, GArray* remote_pending,
                                            guint actor, guint reason)
{
    TIPageChannelGroupPrivate *priv = TI_PAGE_CHANNEL_GROUP_GET_PRIVATE (page_channel_group);
    GtkTextIter iter;
    GString* text = NULL;
    guint i;
    guint handle;

    text = g_string_new ("=== MembersChanged ===\n");

    // Added
    g_string_append (text, "  Added:");
    for (i = 0; i < added->len; i++)
    {
        handle = g_array_index (added, guint, i);
        g_string_append_printf (text, " %u", handle);
    }
    g_string_append (text, "\n");

    // Removed
    g_string_append (text, "  Removed:");
    for (i = 0; i < removed->len; i++)
    {
        handle = g_array_index (removed, guint, i);
        g_string_append_printf (text, " %u", handle);
    }
    g_string_append (text, "\n");

    // Local pending
    g_string_append (text, "  Local pending:");
    for (i = 0; i < local_pending->len; i++)
    {
        handle = g_array_index (local_pending, guint, i);
        g_string_append_printf (text, " %u", handle);
    }
    g_string_append (text, "\n");

    // Remote pending
    g_string_append (text, "  Remote pending:");
    for (i = 0; i < remote_pending->len; i++)
    {
        handle = g_array_index (remote_pending, guint, i);
        g_string_append_printf (text, " %u", handle);
    }
    g_string_append (text, "\n");

    // Actor
    g_string_append_printf (text, "  Actor: %u\n", actor);

    // Reason
    g_string_append_printf (text, "  Reason: %u", reason);
    switch (reason)
    {
        case TI_CHANNEL_GROUP_CHANGE_REASON_NONE:
            g_string_append (text, " (None)\n");
            break;

        case TI_CHANNEL_GROUP_CHANGE_REASON_OFFLINE:
            g_string_append (text, " (Offline)\n");
            break;

        case TI_CHANNEL_GROUP_CHANGE_REASON_KICKED:
            g_string_append (text, " (Kicked)\n");
            break;

        case TI_CHANNEL_GROUP_CHANGE_REASON_BUSY:
            g_string_append (text, "(Busy)\n");
            break;

        case TI_CHANNEL_GROUP_CHANGE_REASON_INVITED:
            g_string_append (text, " (Invited)\n");
            break;

        default:
            g_string_append (text, " (Unknown/Invalid)\n");
    }

    // Space for next entry
    g_string_append (text, "\n");

    // Append to event log
    gtk_text_buffer_get_end_iter (priv->textbuffer_event_log, &iter);
    gtk_text_buffer_insert (priv->textbuffer_event_log, &iter, text->str, -1);

    // Clean up
    if (text != NULL)
        g_string_free (text, TRUE);
}

/**
 * Clear Log
 */
static void
_ti_page_channel_group_clear_log (TIPageChannelGroup* page_channel_group)
{
    TIPageChannelGroupPrivate *priv = TI_PAGE_CHANNEL_GROUP_GET_PRIVATE (page_channel_group);
    GtkTextIter start_iter;
    GtkTextIter end_iter;

    gtk_text_buffer_get_start_iter (priv->textbuffer_event_log, &start_iter);
    gtk_text_buffer_get_end_iter (priv->textbuffer_event_log, &end_iter);

    gtk_text_buffer_delete (priv->textbuffer_event_log, &start_iter, &end_iter);
}

/**
 * Group Flags Changed
 */
static void
_ti_page_channel_group_group_flags_changed (TIPageChannelGroup* page_channel_group, guint added, guint removed)
{
    TIPageChannelGroupPrivate *priv = TI_PAGE_CHANNEL_GROUP_GET_PRIVATE (page_channel_group);
    gboolean can_add;

    // Log it.
    _ti_page_channel_group_log_group_flags_changed (page_channel_group, added, removed);

    priv->group_flags = priv->group_flags + added - removed;

    _ti_page_channel_group_refresh_group_flags_checkboxes (page_channel_group);

    can_add = (priv->group_flags & TI_CHANNEL_GROUP_FLAG_CAN_ADD) != 0;
    gtk_widget_set_sensitive (GTK_WIDGET (priv->button_remove_members), can_add);

    _ti_page_channel_group_update_selection_permissions (page_channel_group);
    _ti_page_channel_group_update_button_remove_sensitivity (page_channel_group);
}

/**
 * Refresh Group Flags Checkboxes
 */
static void
_ti_page_channel_group_refresh_group_flags_checkboxes (TIPageChannelGroup* page_channel_group)
{
    TIPageChannelGroupPrivate *priv = TI_PAGE_CHANNEL_GROUP_GET_PRIVATE (page_channel_group);
    gboolean active;

    active = (priv->group_flags & TI_CHANNEL_GROUP_FLAG_CAN_ADD) != 0;
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->checkbutton_can_add), active);
    
    active = (priv->group_flags & TI_CHANNEL_GROUP_FLAG_CAN_REMOVE) != 0;
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->checkbutton_can_remove), active);
    
    active = (priv->group_flags & TI_CHANNEL_GROUP_FLAG_CAN_RESCIND) != 0;
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->checkbutton_can_rescind), active);
    
    active = (priv->group_flags & TI_CHANNEL_GROUP_FLAG_MESSAGE_ADD) != 0;
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->checkbutton_message_add), active);
    
    active = (priv->group_flags & TI_CHANNEL_GROUP_FLAG_MESSAGE_REMOVE) != 0;
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->checkbutton_message_remove), active);
    
    active = (priv->group_flags & TI_CHANNEL_GROUP_FLAG_MESSAGE_ACCEPT) != 0;
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->checkbutton_message_accept), active);
    
    active = (priv->group_flags & TI_CHANNEL_GROUP_FLAG_MESSAGE_REJECT) != 0;
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->checkbutton_message_reject), active);
    
    active = (priv->group_flags & TI_CHANNEL_GROUP_FLAG_MESSAGE_RESCIND) != 0;
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->checkbutton_message_rescind), active);
    
    active = (priv->group_flags & TI_CHANNEL_GROUP_FLAG_CHANNEL_SPECIFIC_HANDLES) != 0;
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (priv->checkbutton_channel_specific_handles), active);
}

/**
 * Update Selection Permissions
 */
static void
_ti_page_channel_group_update_selection_permissions (TIPageChannelGroup* page_channel_group)
{
 /*   TIPageChannelGroupPrivate *priv = TI_PAGE_CHANNEL_GROUP_GET_PRIVATE (page_channel_group);

    if ((priv->group_flags & TI_CHANNEL_GROUP_FLAG_CAN_REMOVE) != 0)
    {
        gtk_tree_selection_set_mode (priv->members_selection, GTK_SELECTION_MULTIPLE);
    }
    else
    {
        gtk_tree_selection_set_mode (priv->members_selection, GTK_SELECTION_NONE);
    }

    if ((priv->group_flags & TI_CHANNEL_GROUP_FLAG_CAN_RESCIND) != 0)
    {
        gtk_tree_selection_set_mode (priv->remote_pending_selection, GTK_SELECTION_MULTIPLE);
    }
    else
    {
        gtk_tree_selection_set_mode (priv->remote_pending_selection, GTK_SELECTION_NONE);
    }*/
}

/**
 * Log Group Flags Changed
 */
static void
_ti_page_channel_group_log_group_flags_changed (TIPageChannelGroup* page_channel_group, guint added, guint removed)
{
    TIPageChannelGroupPrivate *priv = TI_PAGE_CHANNEL_GROUP_GET_PRIVATE (page_channel_group);
    GtkTextIter iter;
    GString* text;

    text = g_string_new ("=== GroupFlagsChanged ===\n");

    g_string_append (text, "  Added:");
    _group_flags_to_string (text, added);
    g_string_append (text, "\n");

    g_string_append (text, "  Removed:");
    _group_flags_to_string (text, removed);
    g_string_append (text, "\n");

    // Space for the next entry.
    g_string_append (text, "\n");

    // Append to event log
    gtk_text_buffer_get_end_iter (priv->textbuffer_event_log, &iter);
    gtk_text_buffer_insert (priv->textbuffer_event_log, &iter, text->str, -1);

    if (text != NULL)
        g_string_free (text, TRUE);
}

/**
 * Group Flags To String
 */
static void
_group_flags_to_string (GString* text, guint flags)
{
    if ((flags & TI_CHANNEL_GROUP_FLAG_CAN_ADD) != 0)
        g_string_append_printf (text, " Can Add (%u)", TI_CHANNEL_GROUP_FLAG_CAN_ADD);
    
    if ((flags & TI_CHANNEL_GROUP_FLAG_CAN_REMOVE) != 0)
        g_string_append_printf (text, " Can Remove (%u)", TI_CHANNEL_GROUP_FLAG_CAN_REMOVE);
    
    if ((flags & TI_CHANNEL_GROUP_FLAG_CAN_RESCIND) != 0)
        g_string_append_printf (text, " Can Rescind (%u)", TI_CHANNEL_GROUP_FLAG_CAN_RESCIND);
    
    if ((flags & TI_CHANNEL_GROUP_FLAG_MESSAGE_ADD) != 0)
        g_string_append_printf (text, " Message Add (%u)", TI_CHANNEL_GROUP_FLAG_MESSAGE_ADD);

    if ((flags & TI_CHANNEL_GROUP_FLAG_MESSAGE_REMOVE) != 0)
        g_string_append_printf (text, " Message Remove (%u)", TI_CHANNEL_GROUP_FLAG_MESSAGE_REMOVE);
    
    if ((flags & TI_CHANNEL_GROUP_FLAG_MESSAGE_ACCEPT) != 0)
        g_string_append_printf (text, " Message Accept (%u)", TI_CHANNEL_GROUP_FLAG_MESSAGE_ACCEPT);
    
    if ((flags & TI_CHANNEL_GROUP_FLAG_MESSAGE_REJECT) != 0)
        g_string_append_printf (text, " Message Reject (%u)", TI_CHANNEL_GROUP_FLAG_MESSAGE_REJECT);
    
    if ((flags & TI_CHANNEL_GROUP_FLAG_MESSAGE_RESCIND) != 0)
        g_string_append_printf (text, " Message Rescind (%u)", TI_CHANNEL_GROUP_FLAG_MESSAGE_RESCIND);
    
    if ((flags & TI_CHANNEL_GROUP_FLAG_CHANNEL_SPECIFIC_HANDLES) != 0)
        g_string_append_printf (text, " Channel Specific Handles (%u)", TI_CHANNEL_GROUP_FLAG_CHANNEL_SPECIFIC_HANDLES);
}

/**
 * Handle Display Mode Changed
 */
static void
_ti_page_channel_group_handle_display_mode_changed (TIPageChannelGroup* page_channel_group, guint handle_display_mode)
{
    TIPageChannelGroupPrivate *priv = TI_PAGE_CHANNEL_GROUP_GET_PRIVATE (page_channel_group);
    GtkTreeViewColumn* contact_handle_column;
    GtkCellRenderer* renderer;
    GList* renderers_list = NULL;

    g_assert (TI_IS_PAGE_CHANNEL_GROUP (page_channel_group));

    contact_handle_column = gtk_tree_view_get_column (priv->members_tree_view, 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_MEMBERS_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_MEMBERS_LIST_NAME,
                                             NULL);
    }

    // Clean up
    g_list_free (renderers_list);
}

/**
 * Get Contact Row
 */
static gboolean
_ti_page_channel_get_contact_row (TIPageChannelGroup* page_channel_group, guint contact_handle, GtkTreeIter* iter)
{
    TIPageChannelGroupPrivate* priv = TI_PAGE_CHANNEL_GROUP_GET_PRIVATE (page_channel_group);
    gboolean ok;
    gboolean found = FALSE;
    guint curr_handle;

    ok = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (priv->members_list), iter);
    while (ok && !found)
    {
        gtk_tree_model_get (GTK_TREE_MODEL (priv->members_list), iter,
                            TI_COLUMN_MEMBERS_LIST_HANDLE, &curr_handle,
                            -1);

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

    return found;
}

Generated by  Doxygen 1.6.0   Back to index