Mercurial > pidgin
diff src/gtkconv.c @ 9554:8b2451878e26
[gaim-migrate @ 10387]
" This patch adds chat user status icons (voice / halfop
/ op / founder) to chats
There's a screenshot here, showing ops, voices and
ignored ops and voices
http://nosnilmot.com/gaim/chatusers.png
This required some changes in how the core stores the
list of users in chats to be able to store the status
too, which are detailed below.
I also fixed up some memory leaks as I came across them
(string values returned by gtk_tree_model_get() not
being g_free()'d) and a minor bug in signals-test.c
Conversation API:
Changed:
gaim_conv_chat_add_user() (added flags parameter)
gaim_conv_chat_add_users() now (added GList of flags
parameter)
gaim_conv_chat_get_users() now returns a GList of
GaimChatBuddy's
gaim_conv_chat_set_users() now expects a GList of
GaimChatBuddy's
Added:
gaim_conv_chat_set_user_flags()
gaim_conv_chat_get_user_flags()
gaim_conv_chat_find_user()
gaim_conv_chat_cb_new()
gaim_conv_chat_cb_find()
gaim_conv_chat_cb_destroy()
gaim_conv_chat_cb_get_name()
Conversation UI ops:
added: chat_update_user()
Signals:
Changed: chat-buddy-joining & chat-buddy-joined now
include the user's flags
Added: chat-buddy-flags for when user's flags change
Added:
gaim_marshal_VOID__POINTER_POINTER_POINTER_UINT_UINT
(required for the new chat-buddy-flags signal)
Protocol Plugins:
All updated to work with above changes (obviously)
User flags support added to IRC, Jabber and SILC
New Files:
pixmaps/status/default/ voice.svg halfop.svg op.svg
founder.svg
" --Stu Tomlinson
committer: Tailor Script <tailor@pidgin.im>
| author | Luke Schierer <lschiere@pidgin.im> |
|---|---|
| date | Sat, 17 Jul 2004 18:11:12 +0000 |
| parents | 03066f174777 |
| children | d066c21dcbef |
line wrap: on
line diff
--- a/src/gtkconv.c Sat Jul 17 17:08:24 2004 +0000 +++ b/src/gtkconv.c Sat Jul 17 18:11:12 2004 +0000 @@ -126,7 +126,7 @@ static void got_typing_keypress(GaimConversation *conv, gboolean first); static GList *generate_invite_user_names(GaimConnection *gc); static void add_chat_buddy_common(GaimConversation *conv, - const char *name, int pos); + const char *name); static void tab_complete(GaimConversation *conv); static void update_typing_icon(GaimConversation *conv); static gboolean update_send_as_selection(GaimConvWindow *win); @@ -591,7 +591,7 @@ GtkTreeIter iter; GtkTreeModel *model; GtkTreeSelection *sel; - const char *name; + char *name; gtkchat = gtkconv->u.chat; @@ -604,6 +604,7 @@ return; chat_do_info(conv, name); + g_free(name); } } @@ -1196,7 +1197,7 @@ GtkTreeIter iter; GtkTreeModel *model; GtkTreeSelection *sel; - const char *name; + char *name; gtkconv = GAIM_GTK_CONVERSATION(conv); gtkchat = gtkconv->u.chat; @@ -1210,6 +1211,7 @@ return; chat_do_im(conv, name); + g_free(name); } static void @@ -1222,7 +1224,6 @@ GtkTreeModel *model; GtkTreeSelection *sel; const char *name; - int pos; chat = GAIM_CONV_CHAT(conv); gtkconv = GAIM_GTK_CONVERSATION(conv); @@ -1238,14 +1239,12 @@ else return; - pos = g_list_index(gaim_conv_chat_get_users(chat), name); - if (gaim_conv_chat_is_user_ignored(chat, name)) gaim_conv_chat_unignore(chat, name); else gaim_conv_chat_ignore(chat, name); - add_chat_buddy_common(conv, name, pos); + add_chat_buddy_common(conv, name); } static void @@ -1480,6 +1479,7 @@ if (event->button == 1 && event->type == GDK_2BUTTON_PRESS) { chat_do_im(conv, who); + g_free(who); } else if (event->button == 3 && event->type == GDK_BUTTON_PRESS) { GtkWidget *menu = create_chat_menu (conv, who, prpl_info, gc); gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, @@ -3248,23 +3248,41 @@ } static GdkPixbuf * -get_chat_user_status_icon(GaimConvChat *chat, const char *name) +get_chat_buddy_status_icon(GaimConvChat *chat, const char *name, GaimConvChatBuddyFlags flags) { - GdkPixbuf *pixbuf, *scale; + GdkPixbuf *pixbuf, *scale, *scale2; char *filename; - - /* Eventually this should compose the pixbuf based on user status (op, voice, etc.) - * and ignored status and any other fancy things we want to show. For now though, - * it's just ignored users that have the privilege of an icon */ - - if(gaim_conv_chat_is_user_ignored(chat, name)) { - filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "ignored.svg", NULL); + char *image = NULL; + + if (flags & GAIM_CBFLAGS_FOUNDER) { + image = g_strdup("founder.svg"); + } else if (flags & GAIM_CBFLAGS_OP) { + image = g_strdup("op.svg"); + } else if (flags & GAIM_CBFLAGS_HALFOP) { + image = g_strdup("halfop.svg"); + } else if (flags & GAIM_CBFLAGS_VOICE) { + image = g_strdup("voice.svg"); + } else if ((!flags) && gaim_conv_chat_is_user_ignored(chat, name)) { + image = g_strdup("ignored.svg"); + } + if (image) { + filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", image, NULL); + g_free(image); pixbuf = gdk_pixbuf_new_from_file(filename, NULL); g_free(filename); if (!pixbuf) return NULL; scale = gdk_pixbuf_scale_simple(pixbuf, 15, 15, GDK_INTERP_BILINEAR); g_object_unref(pixbuf); + if (flags && gaim_conv_chat_is_user_ignored(chat, name)) { + filename = g_build_filename(DATADIR, "pixmaps", "gaim", "status", "default", "ignored.svg", NULL); + pixbuf = gdk_pixbuf_new_from_file(filename, NULL); + g_free(filename); + scale2 = gdk_pixbuf_scale_simple(pixbuf, 15, 15, GDK_INTERP_BILINEAR); + g_object_unref(pixbuf); + gdk_pixbuf_composite(scale2, scale, 0, 0, 15, 15, 0, 0, 1, 1, GDK_INTERP_BILINEAR, 192); + g_object_unref(scale2); + } return scale; } @@ -3272,11 +3290,12 @@ } static void -add_chat_buddy_common(GaimConversation *conv, const char *name, int pos) +add_chat_buddy_common(GaimConversation *conv, const char *name) { GaimGtkConversation *gtkconv; GaimGtkChatPane *gtkchat; GaimConvChat *chat; + GaimConvChatBuddyFlags flags; GtkTreeIter iter; GtkListStore *ls; GdkPixbuf *pixbuf; @@ -3287,13 +3306,16 @@ ls = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list))); - pixbuf = get_chat_user_status_icon(chat, name); + flags = gaim_conv_chat_user_get_flags(chat, name); + pixbuf = get_chat_buddy_status_icon(chat, name, flags); gtk_list_store_append(ls, &iter); gtk_list_store_set(ls, &iter, CHAT_USERS_ICON_COLUMN, pixbuf, - CHAT_USERS_NAME_COLUMN, name, -1); + CHAT_USERS_NAME_COLUMN, name, CHAT_USERS_FLAGS_COLUMN, flags, -1); gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(ls), CHAT_USERS_NAME_COLUMN, GTK_SORT_ASCENDING); + if (pixbuf) + g_object_unref(pixbuf); } static void @@ -3356,9 +3378,9 @@ nicks != NULL; nicks = nicks->next) { - char *nick = nicks->data; - - strncpy(nick_partial, nick, strlen(entered)); + GaimConvChatBuddy *cb = nicks->data; + + strncpy(nick_partial, cb->name, strlen(entered)); nick_partial[strlen(entered)] = '\0'; if(gaim_utf8_strcasecmp(nick_partial, entered)) continue; @@ -3370,11 +3392,11 @@ * this will only get called once, since from now * on most_matched is >= 0 */ - most_matched = strlen(nick); - partial = g_strdup(nick); + most_matched = strlen(cb->name); + partial = g_strdup(cb->name); } else if (most_matched) { - char *tmp = g_strdup(nick); + char *tmp = g_strdup(cb->name); while (gaim_utf8_strcasecmp(tmp, partial)) { partial[most_matched] = '\0'; @@ -3387,7 +3409,7 @@ g_free(tmp); } - matches = g_list_append(matches, nick); + matches = g_list_append(matches, cb->name); } g_free(nick_partial); @@ -3662,7 +3684,7 @@ _("Block the user"), NULL); gtk_box_pack_start(GTK_BOX(parent), gtkim->block, FALSE, FALSE, 0); - /* Block button */ + /* Send File button */ gtkim->send_file = gaim_gtk_change_text(_("Send File"), gtkim->send_file, GAIM_STOCK_FILE_TRANSFER, GAIM_CONV_IM); gtk_tooltips_set_tip(gtkconv->tooltips, gtkim->send_file, @@ -3852,6 +3874,32 @@ new_topic); } +static gint +sort_chat_users(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer userdata) +{ + GaimConvChatBuddyFlags f1 = 0, f2 = 0; + char *user1 = NULL, *user2 = NULL; + gint ret = 0; + + gtk_tree_model_get(model, a, CHAT_USERS_NAME_COLUMN, &user1, CHAT_USERS_FLAGS_COLUMN, &f1, -1); + gtk_tree_model_get(model, b, CHAT_USERS_NAME_COLUMN, &user2, CHAT_USERS_FLAGS_COLUMN, &f2, -1); + + if (user1 == NULL || user2 == NULL) { + if (!(user1 == NULL && user2 == NULL)) + ret = (user1 == NULL) ? -1: 1; + } else if (f1 != f2) { + /* sort more important users first */ + ret = (f1 > f2) ? -1 : 1; + } else { + ret = g_utf8_collate(user1, user2); + } + + g_free(user1); + g_free(user2); + + return ret; +} + static GtkWidget * setup_chat_pane(GaimConversation *conv) { @@ -3969,7 +4017,10 @@ gtk_box_pack_start(GTK_BOX(lbox), sw, TRUE, TRUE, 0); gtk_widget_show(sw); - ls = gtk_list_store_new(CHAT_USERS_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING); + ls = gtk_list_store_new(CHAT_USERS_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, + G_TYPE_INT); + gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(ls), CHAT_USERS_NAME_COLUMN, + sort_chat_users, NULL, NULL); gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(ls), CHAT_USERS_NAME_COLUMN, GTK_SORT_ASCENDING); @@ -3979,6 +4030,8 @@ col = gtk_tree_view_column_new_with_attributes(NULL, rend, "pixbuf", CHAT_USERS_ICON_COLUMN, NULL); + gtk_tree_view_column_set_clickable(GTK_TREE_VIEW_COLUMN(col), TRUE); + gtk_tree_view_append_column(GTK_TREE_VIEW(list), col); g_signal_connect(G_OBJECT(list), "button_press_event", @@ -5016,11 +5069,11 @@ mdate, message); else g_snprintf(buf, BUF_LONG, "<FONT COLOR=\"#ff0000\"><B>%s</B></FONT>", message); - + g_snprintf(buf2, sizeof(buf2), "<FONT %s><FONT SIZE=\"2\"><!--(%s) --></FONT><B>%s</B></FONT>", sml_attrib, mdate, message); - + gtk_imhtml_append_text(GTK_IMHTML(gtkconv->imhtml), buf2, 0); /* Add the message to a conversations scrollback buffer */ @@ -5157,7 +5210,6 @@ GaimGtkChatPane *gtkchat; char tmp[BUF_LONG]; int num_users; - int pos; chat = GAIM_CONV_CHAT(conv); gtkconv = GAIM_GTK_CONVERSATION(conv); @@ -5175,9 +5227,7 @@ if (gtkconv->make_sound) gaim_sound_play_event(GAIM_SOUND_CHAT_JOIN); - pos = g_list_index(gaim_conv_chat_get_users(chat), user); - - add_chat_buddy_common(conv, user, pos); + add_chat_buddy_common(conv, user); } static void @@ -5189,7 +5239,6 @@ GList *l; char tmp[BUF_LONG]; int num_users; - int pos; chat = GAIM_CONV_CHAT(conv); gtkconv = GAIM_GTK_CONVERSATION(conv); @@ -5205,9 +5254,7 @@ gtk_label_set_text(GTK_LABEL(gtkchat->count), tmp); for (l = users; l != NULL; l = l->next) { - pos = g_list_index(gaim_conv_chat_get_users(chat), (char *)l->data); - - add_chat_buddy_common(conv, (char *)l->data, pos); + add_chat_buddy_common(conv, (char *)l->data); } } @@ -5220,51 +5267,37 @@ GaimGtkChatPane *gtkchat; GtkTreeIter iter; GtkTreeModel *model; - GList *names; - int pos; int f = 1; chat = GAIM_CONV_CHAT(conv); gtkconv = GAIM_GTK_CONVERSATION(conv); gtkchat = gtkconv->u.chat; - for (names = gaim_conv_chat_get_users(chat); - names != NULL; - names = names->next) { - - char *u = (char *)names->data; - - if (!gaim_utf8_strcasecmp(u, old_name)) { - model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); - - if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) - break; - - while (f != 0) { - char *val; - - gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHAT_USERS_NAME_COLUMN, &val, -1); - - if (!gaim_utf8_strcasecmp(old_name, val)) { - gtk_list_store_remove(GTK_LIST_STORE(model), &iter); - break; - } - - f = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter); - - g_free(val); - } - + model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); + + if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) + return; + + while (f != 0) { + char *val; + + gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHAT_USERS_NAME_COLUMN, &val, -1); + + if (!gaim_utf8_strcasecmp(old_name, val)) { + gtk_list_store_remove(GTK_LIST_STORE(model), &iter); + g_free(val); break; } + + f = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter); + + g_free(val); } - if (!names) + if (!gaim_conv_chat_find_user(chat, old_name)) return; - pos = g_list_index(gaim_conv_chat_get_users(chat), new_name); - - add_chat_buddy_common(conv, new_name, pos); + add_chat_buddy_common(conv, new_name); } static void @@ -5275,7 +5308,6 @@ GaimGtkChatPane *gtkchat; GtkTreeIter iter; GtkTreeModel *model; - GList *names; char tmp[BUF_LONG]; int num_users; int f = 1; @@ -5286,41 +5318,33 @@ num_users = g_list_length(gaim_conv_chat_get_users(chat)) - 1; - for (names = gaim_conv_chat_get_users(chat); - names != NULL; - names = names->next) { - - char *u = (char *)names->data; - - if (!gaim_utf8_strcasecmp(u, user)) { - model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); - - if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) - break; - - while (f != 0) { - char *val; - - gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHAT_USERS_NAME_COLUMN, &val, -1); - - if (!gaim_utf8_strcasecmp(user, val)) - gtk_list_store_remove(GTK_LIST_STORE(model), &iter); - - f = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter); - - g_free(val); - } - + model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); + + if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) + return; + + while (f != 0) { + char *val; + + gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHAT_USERS_NAME_COLUMN, &val, -1); + + if (!gaim_utf8_strcasecmp(user, val)) { + gtk_list_store_remove(GTK_LIST_STORE(model), &iter); + g_free(val); break; } + + f = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter); + + g_free(val); } - if (names == NULL) + if (!gaim_conv_chat_find_user(chat, user)) return; g_snprintf(tmp, sizeof(tmp), - ngettext("%d person in room", "%d people in room", - num_users), num_users); + ngettext("%d person in room", "%d people in room", + num_users), num_users); gtk_label_set_text(GTK_LABEL(gtkchat->count), tmp); @@ -5336,7 +5360,6 @@ GaimGtkChatPane *gtkchat; GtkTreeIter iter; GtkTreeModel *model; - GList *names = NULL; GList *l; char tmp[BUF_LONG]; int num_users; @@ -5350,41 +5373,27 @@ g_list_length(users); for (l = users; l != NULL; l = l->next) { - for (names = gaim_conv_chat_get_users(chat); - names != NULL; - names = names->next) { - - char *u = (char *)names->data; - - if (!gaim_utf8_strcasecmp(u, (char *)l->data)) { - model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); - - if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), - &iter)) - break; - - do { - char *val; - - gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, - CHAT_USERS_NAME_COLUMN, &val, -1); - - if (!gaim_utf8_strcasecmp((char *)l->data, val)) - gtk_list_store_remove(GTK_LIST_STORE(model), &iter); - - f = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter); - - g_free(val); - } while (f); - - break; - } - } + model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); + + if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), + &iter)) + continue; + + do { + char *val; + + gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, + CHAT_USERS_NAME_COLUMN, &val, -1); + + if (!gaim_utf8_strcasecmp((char *)l->data, val)) + f = gtk_list_store_remove(GTK_LIST_STORE(model), &iter); + else + f = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter); + + g_free(val); + } while (f); } - if (names == NULL) - return; - g_snprintf(tmp, sizeof(tmp), ngettext("%d person in room", "%d people in room", num_users), num_users); @@ -5392,6 +5401,47 @@ gtk_label_set_text(GTK_LABEL(gtkchat->count), tmp); } +static void +gaim_gtkconv_chat_update_user(GaimConversation *conv, const char *user) +{ + GaimConvChat *chat; + GaimGtkConversation *gtkconv; + GaimGtkChatPane *gtkchat; + GtkTreeIter iter; + GtkTreeModel *model; + int f = 1; + + chat = GAIM_CONV_CHAT(conv); + gtkconv = GAIM_GTK_CONVERSATION(conv); + gtkchat = gtkconv->u.chat; + + model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list)); + + if (!gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter)) + return; + + while (f != 0) { + char *val; + + gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, CHAT_USERS_NAME_COLUMN, &val, -1); + + if (!gaim_utf8_strcasecmp(user, val)) { + gtk_list_store_remove(GTK_LIST_STORE(model), &iter); + g_free(val); + break; + } + + f = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter); + + g_free(val); + } + + if (!gaim_conv_chat_find_user(chat, user)) + return; + + add_chat_buddy_common(conv, user); +} + static gboolean gaim_gtkconv_has_focus(GaimConversation *conv) { @@ -5514,9 +5564,9 @@ topic = gaim_conv_chat_get_topic(chat); - gtk_entry_set_text(GTK_ENTRY(gtkchat->topic_text),topic); + gtk_entry_set_text(GTK_ENTRY(gtkchat->topic_text), topic ? topic : ""); gtk_tooltips_set_tip(gtkconv->tooltips, gtkchat->topic_text, - topic, NULL); + topic ? topic : "", NULL); } else if (type == GAIM_CONV_ACCOUNT_ONLINE || type == GAIM_CONV_ACCOUNT_OFFLINE) @@ -5553,6 +5603,7 @@ gaim_gtkconv_chat_rename_user, /* chat_rename_user */ gaim_gtkconv_chat_remove_user, /* chat_remove_user */ gaim_gtkconv_chat_remove_users, /* chat_remove_users */ + gaim_gtkconv_chat_update_user, /* chat_update_user */ NULL, /* update_progress */ gaim_gtkconv_has_focus, /* has_focus */ gaim_gtkconv_updated /* updated */
