Mercurial > pidgin
view src/protocols/qq/group_admindlg.c @ 13967:99b9b58b19dd
[gaim-migrate @ 16523]
Fix a crazy MSN crash. Basically it's possible to have more than one
slplink associated with a given switchboard, but our code did not
allow for that. I think it happens when you're in a multi-user
chat and you do stuff with multiple users that involves slplinks.
Like maybe file transfer and buddy icon related stuff.
Tracking this down took an ungodly amount of time, but thanks to
Meebo for letting me do it :-)
committer: Tailor Script <tailor@pidgin.im>
author | Mark Doliner <mark@kingant.net> |
---|---|
date | Thu, 20 Jul 2006 07:31:15 +0000 |
parents | 983fd420e86b |
children |
line wrap: on
line source
/** * The QQ2003C protocol plugin * * for gaim * * Copyright (C) 2004 Puzzlebird * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // START OF FILE /*****************************************************************************/ #include "debug.h" // gaim_debug #include "blist.h" // GAIM_BLIST_NODE_IS_BUDDY #include "notify.h" // gaim_notify_warning #include "utils.h" // gaim_name_to_uid #include "group_admindlg.h" #include "group_find.h" // qq_group_find_by_internal_group_id #include "group_join.h" // auth_type #include "group_opt.h" // QQ_GROUP_TYPE_PERMANENT enum { COLUMN_SELECTED = 0, COLUMN_UID, COLUMN_NICKNAME, NUM_COLUMNS }; enum { PAGE_INFO = 0, PAGE_MEMBER, }; typedef struct _qun_info_window { guint32 internal_group_id; GaimConnection *gc; GtkWidget *window; GtkWidget *notebook; GtkWidget *lbl_external_group_id; GtkWidget *lbl_admin_uid; GtkWidget *ent_group_name; GtkWidget *cmb_group_category; GtkWidget *txt_group_desc; GtkWidget *txt_group_notice; GtkWidget *rad_auth[3]; GtkWidget *btn_mod; GtkWidget *btn_close; GtkWidget *tre_members; } qun_info_window; const gchar *qq_group_category[] = { "同学", "朋友", "同事", "其他", }; // qq_group_category const gchar *qq_group_auth_type_desc[] = { "无须认证", "需要认证", "不可添加", }; // qq_group_auth_type_desc /*****************************************************************************/ static void _qq_group_info_window_deleteevent(GtkWidget * widget, GdkEvent * event, gpointer data) { gtk_widget_destroy(widget); // this will call _window_destroy } // _window_deleteevent /*****************************************************************************/ static void _qq_group_info_window_close(GtkWidget * widget, gpointer data) { // this will call _info_window_destroy if it is info-window gtk_widget_destroy(GTK_WIDGET(data)); } // _window_close /*****************************************************************************/ static void _qq_group_info_window_destroy(GtkWidget * widget, gpointer data) { GaimConnection *gc; GList *list; qq_data *qd; qun_info_window *info_window; gc = (GaimConnection *) data; g_return_if_fail(gc != NULL && gc->proto_data != NULL); gaim_debug(GAIM_DEBUG_INFO, "QQ", "Group info is destoryed\n"); qd = (qq_data *) gc->proto_data; list = qd->qun_info_window; while (list) { info_window = (qun_info_window *) (list->data); if (info_window->window != widget) list = list->next; else { qd->qun_info_window = g_list_remove(qd->qun_info_window, info_window); g_free(info_window); break; } // if info_window } // while } // _window_destroy /*****************************************************************************/ void qq_qun_info_window_free(qq_data * qd) { gint i; qun_info_window *info_window; i = 0; while (qd->qun_info_window) { info_window = (qun_info_window *) qd->qun_info_window->data; qd->qun_info_window = g_list_remove(qd->qun_info_window, info_window); if (info_window->window) gtk_widget_destroy(info_window->window); g_free(info_window); i++; } // while gaim_debug(GAIM_DEBUG_INFO, "QQ", "%d Qun info windows are freed\n", i); } // qq_qun_info_window_free /*****************************************************************************/ static void _qq_group_info_window_modify(GtkWidget * widget, gpointer data) { GaimConnection *gc; qun_info_window *info_window; g_return_if_fail(data != NULL); info_window = (qun_info_window *) data; gc = info_window->gc; g_return_if_fail(gc != NULL && gc->proto_data != NULL); //henry: This function contains some codes only supported by gtk-2.4 or later //#if !GTK_CHECK_VERSION(2,4,0) // gaim_notify_info(gc, _("QQ Qun Operation"), // _("This version of GTK-2 does not support this function"), NULL); // return; //#else gint page, group_category, i = 0; qq_group *group; qq_data *qd; GtkTextIter start, end; GtkTreeModel *model; GtkTreeIter iter; GValue value = { 0, }; guint32 *new_members; guint32 uid; gboolean selected; qd = (qq_data *) gc->proto_data; // we assume the modification can succeed // maybe it needs some tweak here group = qq_group_find_by_internal_group_id(gc, info_window->internal_group_id); g_return_if_fail(group != NULL); new_members = g_newa(guint32, QQ_QUN_MEMBER_MAX); page = gtk_notebook_get_current_page(GTK_NOTEBOOK(info_window->notebook)); switch (page) { case PAGE_INFO: gaim_debug(GAIM_DEBUG_INFO, "QQ", "Gonna change Qun detailed information\n"); // get the group_category #if GTK_CHECK_VERSION(2,4,0) group_category = gtk_combo_box_get_active(GTK_COMBO_BOX(info_window->cmb_group_category)); #else group_category = gtk_option_menu_get_history(GTK_OPTION_MENU(info_window->cmb_group_category)); #endif if (group_category >= 0) group->group_category = group_category; else { g_free(group); gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Invalid group_category: %d\n", group_category); return; } // if group_category // get auth_type if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(info_window->rad_auth[0]))) group->auth_type = QQ_GROUP_AUTH_TYPE_NO_AUTH; else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(info_window->rad_auth[1]))) group->auth_type = QQ_GROUP_AUTH_TYPE_NEED_AUTH; else group->auth_type = QQ_GROUP_AUTH_TYPE_NO_ADD; // MUST use g_strdup, otherwise core dump after info_window is closed group->group_name_utf8 = g_strdup(gtk_entry_get_text(GTK_ENTRY(info_window->ent_group_name))); gtk_text_buffer_get_bounds(gtk_text_view_get_buffer (GTK_TEXT_VIEW(info_window->txt_group_desc)), &start, &end); group->group_desc_utf8 = g_strdup(gtk_text_buffer_get_text (gtk_text_view_get_buffer (GTK_TEXT_VIEW(info_window->txt_group_desc)), &start, &end, FALSE)); gtk_text_buffer_get_bounds(gtk_text_view_get_buffer (GTK_TEXT_VIEW(info_window->txt_group_notice)), &start, &end); group->notice_utf8 = g_strdup(gtk_text_buffer_get_text (gtk_text_view_get_buffer (GTK_TEXT_VIEW(info_window->txt_group_notice)), &start, &end, FALSE)); // finally we can modify it with new information qq_group_modify_info(gc, group); break; case PAGE_MEMBER: if (info_window->tre_members == NULL) { gaim_debug(GAIM_DEBUG_INFO, "QQ", "Member list is not ready, cannot modify!\n"); } else { gaim_debug(GAIM_DEBUG_INFO, "QQ", "Gonna change Qun member list\n"); model = gtk_tree_view_get_model(GTK_TREE_VIEW(info_window->tre_members)); if (gtk_tree_model_get_iter_first(model, &iter)) { gtk_tree_model_get_value(model, &iter, COLUMN_UID, &value); uid = g_value_get_uint(&value); g_value_unset(&value); gtk_tree_model_get_value(model, &iter, COLUMN_SELECTED, &value); selected = g_value_get_boolean(&value); g_value_unset(&value); if (!selected) new_members[i++] = uid; while (gtk_tree_model_iter_next(model, &iter)) { gtk_tree_model_get_value(model, &iter, COLUMN_UID, &value); uid = g_value_get_uint(&value); g_value_unset(&value); gtk_tree_model_get_value(model, &iter, COLUMN_SELECTED, &value); selected = g_value_get_boolean(&value); g_value_unset(&value); if (!selected) new_members[i++] = uid; } // while new_members[i] = 0xffffffff; // this labels the end } else new_members[0] = 0xffffffff; qq_group_modify_members(gc, group, new_members); } // if info_window->tre_members break; default: gaim_debug(GAIM_DEBUG_INFO, "QQ", "Invalid page number: %d\n", page); } // switch _qq_group_info_window_close(NULL, info_window->window); //#endif /* GTK_CHECK_VERSION */ } // _qq_group_info_window_modify /*****************************************************************************/ static void _qq_group_member_list_deleted_toggled(GtkCellRendererToggle * cell, gchar * path_str, gpointer data) { qun_info_window *info_window; GaimConnection *gc; qq_group *group; info_window = (qun_info_window *) data; g_return_if_fail(info_window != NULL); gc = info_window->gc; g_return_if_fail(gc != NULL); group = qq_group_find_by_internal_group_id(gc, info_window->internal_group_id); g_return_if_fail(group != NULL); GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(info_window->tre_members)); GtkTreeIter iter; GtkTreePath *path = gtk_tree_path_new_from_string(path_str); gboolean selected; guint32 uid; gtk_tree_model_get_iter(model, &iter, path); gtk_tree_model_get(model, &iter, COLUMN_SELECTED, &selected, -1); gtk_tree_model_get(model, &iter, COLUMN_UID, &uid, -1); if (uid != group->creator_uid) { // do not allow delete admin selected ^= 1; gtk_list_store_set(GTK_LIST_STORE(model), &iter, COLUMN_SELECTED, selected, -1); gtk_tree_path_free(path); } else gaim_notify_error(gc, NULL, _("Qun creator cannot be removed"), NULL); } // _qq_group_member_list_deleted_toggled /*****************************************************************************/ static void _qq_group_member_list_drag_data_rcv_cb (GtkWidget * widget, GdkDragContext * dc, guint x, guint y, GtkSelectionData * sd, guint info, guint t, gpointer data) { GaimConnection *gc; GaimAccount *account; GaimBlistNode *n = NULL; GaimContact *c = NULL; GaimBuddy *b = NULL; GtkWidget *treeview; GtkTreeModel *model; GtkListStore *store; GtkTreeIter iter; GValue value = { 0, }; guint32 uid, input_uid; treeview = widget; gc = (GaimConnection *) data; g_return_if_fail(gc != NULL); account = gaim_connection_get_account(gc); if (sd->target != gdk_atom_intern("GAIM_BLIST_NODE", FALSE) || sd->data == NULL) { gaim_debug(GAIM_DEBUG_ERROR, "QQ", "Invalid drag data received, discard...\n"); return; } // if (sd->target memcpy(&n, sd->data, sizeof(n)); // we expect GAIM_BLIST_CONTACT_NODE and GAIM_BLIST_BUDDY_NODE if (GAIM_BLIST_NODE_IS_CONTACT(n)) { c = (GaimContact *) n; b = c->priority; // we get the first buddy only } else if (GAIM_BLIST_NODE_IS_BUDDY(n)) b = (GaimBuddy *) n; if (b == NULL) { gaim_debug(GAIM_DEBUG_ERROR, "QQ", "No valid GaimBuddy is passed from DnD\n"); return; } // if b == NULL gaim_debug(GAIM_DEBUG_INFO, "QQ", "We get a GaimBuddy: %s\n", b->name); input_uid = gaim_name_to_uid(b->name); g_return_if_fail(input_uid > 0); model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview)); // we need to check if the user id in the member list is unique // possibly a tree transverse is necessary to achieve this if (gtk_tree_model_get_iter_first(model, &iter)) { gtk_tree_model_get_value(model, &iter, COLUMN_UID, &value); uid = g_value_get_uint(&value); g_value_unset(&value); while (uid != input_uid && gtk_tree_model_iter_next(model, &iter)) { gtk_tree_model_get_value(model, &iter, COLUMN_UID, &value); uid = g_value_get_uint(&value); g_value_unset(&value); } // while } else uid = 0; // if gtk_tree_model_get_iter_first if (uid == input_uid) { gaim_debug(GAIM_DEBUG_WARNING, "QQ", "Qun already has this buddy %s\n", b->name); return; } else { // we add it to list store = GTK_LIST_STORE(model); gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, COLUMN_SELECTED, FALSE, COLUMN_UID, input_uid, COLUMN_NICKNAME, b->alias, -1); // re-sort the list gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), COLUMN_UID, GTK_SORT_ASCENDING); } // if uid } // _qq_group_member_list_drag_data_rcv_cb /*****************************************************************************/ static GtkWidget *_create_page_info(GaimConnection * gc, qq_group * group, gboolean do_manage, qun_info_window * info_window) { GtkWidget *vbox, *hbox; GtkWidget *frame_info, *frame_auth; GtkWidget *tbl_info; GtkWidget *label, *entry, *combo, *text, *scrolled_window; gint i; g_return_val_if_fail(gc != NULL && group != NULL, NULL); vbox = gtk_vbox_new(FALSE, 5); frame_info = gtk_frame_new(NULL); gtk_box_pack_start(GTK_BOX(vbox), frame_info, TRUE, TRUE, 0); tbl_info = gtk_table_new(6, 4, FALSE); gtk_table_set_row_spacings(GTK_TABLE(tbl_info), 4); gtk_table_set_col_spacing(GTK_TABLE(tbl_info), 1, 10); gtk_container_add(GTK_CONTAINER(frame_info), tbl_info); label = gtk_label_new(_("Group ID: ")); gtk_table_attach(GTK_TABLE(tbl_info), label, 0, 1, 0, 1, GTK_FILL, GTK_FILL, 0, 0); label = gtk_label_new(g_strdup_printf("%d", group->external_group_id)); gtk_table_attach(GTK_TABLE(tbl_info), label, 1, 2, 0, 1, GTK_FILL, GTK_FILL, 0, 0); info_window->lbl_external_group_id = label; label = gtk_label_new(_("Group Name")); gtk_table_attach(GTK_TABLE(tbl_info), label, 2, 3, 0, 1, GTK_FILL, GTK_FILL, 0, 0); entry = gtk_entry_new(); gtk_widget_set_size_request(entry, 100, -1); if (group->group_name_utf8 != NULL) gtk_entry_set_text(GTK_ENTRY(entry), group->group_name_utf8); gtk_table_attach(GTK_TABLE(tbl_info), entry, 3, 4, 0, 1, GTK_FILL, GTK_FILL, 0, 0); info_window->ent_group_name = entry; label = gtk_label_new(_("Admin: ")); gtk_table_attach(GTK_TABLE(tbl_info), label, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0); label = gtk_label_new(g_strdup_printf("%d", group->creator_uid)); gtk_table_attach(GTK_TABLE(tbl_info), label, 1, 2, 1, 2, GTK_FILL, GTK_FILL, 0, 0); info_window->lbl_admin_uid = label; label = gtk_label_new(_("Category")); gtk_table_attach(GTK_TABLE(tbl_info), label, 2, 3, 1, 2, GTK_FILL, GTK_FILL, 0, 0); //henry: these codes are supported only in GTK-2.4 or later #if GTK_CHECK_VERSION(2, 4, 0) combo = gtk_combo_box_new_text(); for (i = 0; i < 4; i++) gtk_combo_box_append_text(GTK_COMBO_BOX(combo), qq_group_category[i]); gtk_combo_box_set_active(GTK_COMBO_BOX(combo), group->group_category); #else GtkWidget *menu; GtkWidget *item; combo = gtk_option_menu_new(); menu = gtk_menu_new(); for (i = 0; i < 4; i++) { item = gtk_menu_item_new_with_label(qq_group_category[i]); gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); gtk_widget_show(item); } gtk_option_menu_set_menu(GTK_OPTION_MENU(combo), menu); gtk_option_menu_set_history(GTK_OPTION_MENU(combo), group->group_category); #endif /* GTK_CHECK_VERSION */ gtk_table_attach(GTK_TABLE(tbl_info), combo, 3, 4, 1, 2, GTK_FILL, GTK_FILL, 0, 0); info_window->cmb_group_category = combo; label = gtk_label_new(_("Description")); gtk_table_attach(GTK_TABLE(tbl_info), label, 0, 1, 2, 3, GTK_FILL, GTK_FILL, 0, 0); text = gtk_text_view_new(); gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD); gtk_widget_set_size_request(text, -1, 50); if (group->group_desc_utf8 != NULL) gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)), group->group_desc_utf8, -1); info_window->txt_group_desc = text; scrolled_window = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_container_add(GTK_CONTAINER(scrolled_window), text); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window), GTK_SHADOW_IN); gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text), 2); gtk_text_view_set_right_margin(GTK_TEXT_VIEW(text), 2); gtk_table_attach(GTK_TABLE(tbl_info), scrolled_window, 0, 4, 3, 4, GTK_FILL, GTK_FILL, 0, 0); label = gtk_label_new(_("Group Notice")); gtk_table_attach(GTK_TABLE(tbl_info), label, 0, 1, 4, 5, GTK_FILL, GTK_FILL, 0, 0); text = gtk_text_view_new(); gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD); gtk_widget_set_size_request(text, -1, 50); if (group->notice_utf8 != NULL) gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(text)), group->notice_utf8, -1); info_window->txt_group_notice = text; scrolled_window = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_container_add(GTK_CONTAINER(scrolled_window), text); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_window), GTK_SHADOW_IN); gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text), 2); gtk_text_view_set_right_margin(GTK_TEXT_VIEW(text), 2); gtk_table_attach(GTK_TABLE(tbl_info), scrolled_window, 0, 4, 5, 6, GTK_FILL, GTK_FILL, 0, 0); frame_auth = gtk_frame_new(_("Authentication")); hbox = gtk_hbox_new(FALSE, 5); gtk_container_add(GTK_CONTAINER(frame_auth), hbox); info_window->rad_auth[0] = gtk_radio_button_new_with_label(NULL, qq_group_auth_type_desc[0]); info_window->rad_auth[1] = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON (info_window->rad_auth[0]), qq_group_auth_type_desc[1]); info_window->rad_auth[2] = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON (info_window->rad_auth[0]), qq_group_auth_type_desc[2]); for (i = 0; i < 3; i++) gtk_box_pack_start(GTK_BOX(hbox), info_window->rad_auth[i], FALSE, FALSE, 0); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(info_window->rad_auth[group->auth_type - 1]), TRUE); gtk_box_pack_start(GTK_BOX(vbox), frame_auth, FALSE, FALSE, 0); if (!do_manage) { gtk_widget_set_sensitive(frame_info, FALSE); gtk_widget_set_sensitive(frame_auth, FALSE); } // if ! do_manage return vbox; } // _create_info_page /*****************************************************************************/ static GtkWidget *_create_page_members (GaimConnection * gc, qq_group * group, gboolean do_manage, qun_info_window * info_window) { GtkWidget *vbox, *sw, *treeview; GtkTreeModel *model; GtkListStore *store; GtkTreeIter iter; GtkCellRenderer *renderer; GtkTreeViewColumn *column; GList *list; qq_buddy *q_bud; GtkTargetEntry gte = { "GAIM_BLIST_NODE", GTK_TARGET_SAME_APP, 0 }; g_return_val_if_fail(gc != NULL && group != NULL, NULL); vbox = gtk_vbox_new(FALSE, 0); if (group->members == NULL) { // if NULL, not ready sw = gtk_label_new(_ ("OpenQ is collecting member information.\nPlease close this window and open again")); gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0); return vbox; } // if group->members sw = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_box_pack_start(GTK_BOX(vbox), sw, TRUE, TRUE, 0); store = gtk_list_store_new(NUM_COLUMNS, G_TYPE_BOOLEAN, G_TYPE_UINT, G_TYPE_STRING); list = group->members; while (list != NULL) { q_bud = (qq_buddy *) list->data; gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, COLUMN_SELECTED, FALSE, COLUMN_UID, q_bud->uid, COLUMN_NICKNAME, q_bud->nickname, -1); list = list->next; } // for model = GTK_TREE_MODEL(store); treeview = gtk_tree_view_new_with_model(model); info_window->tre_members = treeview; gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE); gtk_tree_view_set_search_column(GTK_TREE_VIEW(treeview), COLUMN_UID); g_object_unref(model); // set up drag & drop ONLY for managable Qun if (do_manage) { gtk_tree_view_enable_model_drag_dest(GTK_TREE_VIEW(treeview), >e, 1, GDK_ACTION_COPY); g_signal_connect(G_OBJECT(treeview), "drag-data-received", G_CALLBACK(_qq_group_member_list_drag_data_rcv_cb), gc); } // if do manage gtk_container_add(GTK_CONTAINER(sw), treeview); model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview)); renderer = gtk_cell_renderer_toggle_new(); // it seems this signal has to be handled // otherwise, the checkbox in the column does not reponse to user action if (do_manage) g_signal_connect(renderer, "toggled", G_CALLBACK(_qq_group_member_list_deleted_toggled), info_window); column = gtk_tree_view_column_new_with_attributes(_("Del"), renderer, "active", COLUMN_SELECTED, NULL); gtk_tree_view_column_set_sizing(GTK_TREE_VIEW_COLUMN(column), GTK_TREE_VIEW_COLUMN_FIXED); gtk_tree_view_column_set_fixed_width(GTK_TREE_VIEW_COLUMN(column), 30); gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes(_("UID"), renderer, "text", COLUMN_UID, NULL); gtk_tree_view_column_set_sort_column_id(column, COLUMN_UID); gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); // default sort by UID gtk_tree_view_column_set_sort_order(column, GTK_SORT_ASCENDING); gtk_tree_view_column_set_sort_indicator(column, TRUE); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes(_("Nickname"), renderer, "text", COLUMN_NICKNAME, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), column); return vbox; } // _create_page_members /*****************************************************************************/ void qq_group_detail_window_show(GaimConnection * gc, qq_group * group) { GtkWidget *vbox, *notebook; GtkWidget *label, *bbox; GList *list; qq_data *qd; qun_info_window *info_window = NULL; gboolean do_manage, do_show, do_exist; g_return_if_fail(gc != NULL && gc->proto_data != NULL && group != NULL); qd = (qq_data *) gc->proto_data; do_manage = group->my_status == QQ_GROUP_MEMBER_STATUS_IS_ADMIN; do_show = do_manage || (group->my_status == QQ_GROUP_MEMBER_STATUS_IS_MEMBER); if (!do_show) { gaim_notify_error(gc, _("QQ Qun Operation"), _("You can not view Qun details"), _("Only Qun admin or Qun member can view details")); return; } // if ! do_show list = qd->qun_info_window; do_exist = FALSE; while (list != NULL) { info_window = (qun_info_window *) list->data; if (info_window->internal_group_id == group->internal_group_id) { break; do_exist = TRUE; } else list = list->next; } // while list if (!do_exist) { info_window = g_new0(qun_info_window, 1); info_window->gc = gc; info_window->internal_group_id = group->internal_group_id; g_list_append(qd->qun_info_window, info_window); info_window->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); g_signal_connect(GTK_WINDOW(info_window->window), "delete_event", G_CALLBACK(_qq_group_info_window_deleteevent), NULL); g_signal_connect(G_OBJECT(info_window->window), "destroy", G_CALLBACK(_qq_group_info_window_destroy), gc); gtk_window_set_title(GTK_WINDOW(info_window->window), _("Manage Qun")); gtk_window_set_resizable(GTK_WINDOW(info_window->window), FALSE); gtk_container_set_border_width(GTK_CONTAINER(info_window->window), 5); vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(info_window->window), vbox); notebook = gtk_notebook_new(); info_window->notebook = notebook; gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_TOP); gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0); label = gtk_label_new(_("Qun Information")); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), _create_page_info(gc, group, do_manage, info_window), label); label = gtk_label_new(_("Members")); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), _create_page_members(gc, group, do_manage, info_window), label); bbox = gtk_hbutton_box_new(); gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_SPREAD); gtk_box_set_spacing(GTK_BOX(bbox), 10); info_window->btn_mod = gtk_button_new_with_label(_("Modify")); gtk_container_add(GTK_CONTAINER(bbox), info_window->btn_mod); g_signal_connect(G_OBJECT(info_window->btn_mod), "clicked", G_CALLBACK(_qq_group_info_window_modify), info_window); info_window->btn_close = gtk_button_new_with_label(_("Close")); gtk_container_add(GTK_CONTAINER(bbox), info_window->btn_close); g_signal_connect(G_OBJECT(info_window->btn_close), "clicked", G_CALLBACK(_qq_group_info_window_close), info_window->window); if (!do_manage) gtk_widget_set_sensitive(info_window->btn_mod, FALSE); gtk_box_pack_start(GTK_BOX(vbox), bbox, TRUE, TRUE, 5); gtk_widget_show_all(info_window->window); } else // we already have this gtk_widget_grab_focus(info_window->window); } // qq_group_manage_window_show /*****************************************************************************/ // END OF FILE