Mercurial > pidgin.yaz
diff console/gntblist.c @ 14041:27182f83b79b
[gaim-migrate @ 16647]
Statusbox comes in. It's now possible to change the account status. There's
nothing yet for creating custom statuses.
It's also possible now to delete accounts.
committer: Tailor Script <tailor@pidgin.im>
author | Sadrul Habib Chowdhury <imadil@gmail.com> |
---|---|
date | Sat, 05 Aug 2006 11:31:54 +0000 |
parents | 7109e6397a31 |
children | 143474e2b1cb |
line wrap: on
line diff
--- a/console/gntblist.c Sat Aug 05 09:19:14 2006 +0000 +++ b/console/gntblist.c Sat Aug 05 11:31:54 2006 +0000 @@ -1,19 +1,25 @@ #include <account.h> #include <blist.h> #include <request.h> +#include <savedstatuses.h> #include <server.h> #include <signal.h> +#include <status.h> #include <util.h> #include "gntgaim.h" #include "gntbox.h" +#include "gntcombobox.h" +#include "gntentry.h" #include "gntlabel.h" +#include "gntline.h" #include "gnttree.h" #include "gntblist.h" #include <string.h> #define PREF_ROOT "/gaim/gnt/blist" +#define TYPING_TIMEOUT 4000 typedef struct { @@ -25,8 +31,29 @@ GntWidget *context; GaimBlistNode *cnode; + + /* XXX: I am KISSing */ + GntWidget *status; /* Dropdown with the statuses */ + GntWidget *statustext; /* Status message */ + int typing; } GGBlist; +typedef enum +{ + STATUS_PRIMITIVE = 0, + STATUS_SAVED +} StatusType; + +typedef struct +{ + StatusType type; + union + { + GaimStatusPrimitive prim; + GaimSavedStatus *saved; + } u; +} StatusBoxItem; + GGBlist *ggblist; static void add_buddy(GaimBuddy *buddy, GGBlist *ggblist); @@ -34,6 +61,7 @@ static void add_chat(GaimChat *chat, GGBlist *ggblist); static void add_node(GaimBlistNode *node, GGBlist *ggblist); static void draw_tooltip(GGBlist *ggblist); +static void remove_typing_cb(gpointer null); static void remove_peripherals(GGBlist *ggblist); static const char * get_display_name(GaimBlistNode *node); @@ -113,7 +141,7 @@ { } -static GaimBlistUiOps blist_ui_ops = +static GaimBlistUiOps blist_ui_ops = { new_list, new_node, @@ -202,6 +230,8 @@ GaimBlistNode *node = (GaimBlistNode *)chat; if (node->ui_data) return; + if (!gaim_account_is_connected(chat->account)) + return; group = gaim_chat_get_group(chat); add_node((GaimBlistNode*)group, ggblist); @@ -290,7 +320,7 @@ GList *list; if (action == NULL) return; - + gnt_tree_add_row_after(tree, action, gnt_tree_create_row(tree, action->label), parent, NULL); for (list = action->children; list; list = list->next) @@ -367,7 +397,7 @@ add_custom_action(tree, _("View Log"), GAIM_CALLBACK(gg_blist_view_log_cb)), buddy); #endif - + /* Protocol actions */ append_proto_menu(tree, gaim_account_get_connection(gaim_buddy_get_account(buddy)), @@ -436,9 +466,9 @@ name = ((GaimGroup*)node)->name; else g_return_if_reached(); - + prompt = g_strdup_printf(_("Please enter the new name for %s"), name); - + gaim_request_input(node, _("Rename"), prompt, _("Enter empty string to reset the name."), name, FALSE, FALSE, NULL, _("Rename"), G_CALLBACK(rename_blist_node), _("Cancel"), NULL, node); @@ -682,7 +712,7 @@ ret = gnt_widget_key_pressed(ggblist->context, text); stop = TRUE; } - + if (text[0] == 27) { if (strcmp(text + 1, GNT_KEY_POPUP) == 0) @@ -760,7 +790,8 @@ node->ui_data = NULL; node = gaim_blist_node_next(node, TRUE); } - + + remove_typing_cb(NULL); remove_peripherals(ggblist); g_free(ggblist); ggblist = NULL; @@ -777,10 +808,55 @@ while (node) { node_update(list, node); - node = gaim_blist_node_next(node, TRUE); + node = gaim_blist_node_next(node, FALSE); } } +static void +destroy_status_list(GList *list) +{ + g_list_foreach(list, (GFunc)g_free, NULL); + g_list_free(list); +} + +static void +populate_status_dropdown() +{ + int i; + GList *iter; + GList *items = NULL; + + /* First the primitives */ + GaimStatusPrimitive prims[] = {GAIM_STATUS_AVAILABLE, GAIM_STATUS_AWAY, + GAIM_STATUS_INVISIBLE, GAIM_STATUS_OFFLINE, GAIM_STATUS_UNSET}; + + for (i = 0; prims[i] != GAIM_STATUS_UNSET; i++) + { + StatusBoxItem *item = g_new0(StatusBoxItem, 1); + item->type = STATUS_PRIMITIVE; + item->u.prim = prims[i]; + items = g_list_prepend(items, item); + gnt_combo_box_add_data(GNT_COMBO_BOX(ggblist->status), item, + gaim_primitive_get_name_from_type(prims[i])); + } + + /* Now the popular statuses */ + for (iter = gaim_savedstatuses_get_popular(6); iter; iter = iter->next) + { + StatusBoxItem *item = g_new0(StatusBoxItem, 1); + item->type = STATUS_SAVED; + item->u.saved = iter->data; + items = g_list_prepend(items, item); + gnt_combo_box_add_data(GNT_COMBO_BOX(ggblist->status), item, + gaim_savedstatus_get_title(iter->data)); + } + + /* The keys for the combobox are created here, and never used + * anywhere else. So make sure the keys are freed when the widget + * is destroyed. */ + g_object_set_data_full(G_OBJECT(ggblist->status), "list of statuses", items, (GDestroyNotify)destroy_status_list); +} + void gg_blist_init() { gaim_prefs_add_none(PREF_ROOT); @@ -796,6 +872,120 @@ return; } +static void +remove_typing_cb(gpointer null) +{ + GaimSavedStatus *current; + const char *message, *newmessage; + GaimStatusPrimitive prim, newprim; + StatusBoxItem *item; + + current = gaim_savedstatus_get_current(); + message = gaim_savedstatus_get_message(current); + prim = gaim_savedstatus_get_type(current); + + newmessage = gnt_entry_get_text(GNT_ENTRY(ggblist->statustext)); + item = gnt_combo_box_get_selected_data(GNT_COMBO_BOX(ggblist->status)); + g_return_if_fail(item->type == STATUS_PRIMITIVE); + newprim = item->u.prim; + + if (newprim != prim || ((message && !newmessage) || + (!message && newmessage) || + (message && newmessage && g_utf8_collate(message, newmessage) != 0))) + { + GaimSavedStatus *status = gaim_savedstatus_find_transient_by_type_and_message(newprim, newmessage); + /* Holy Crap! That's a LAWNG function name */ + if (status == NULL) + { + status = gaim_savedstatus_new(NULL, newprim); + gaim_savedstatus_set_message(status, newmessage); + } + + gaim_savedstatus_activate(status); + } + + gnt_box_give_focus_to_child(GNT_BOX(ggblist->window), ggblist->tree); + g_source_remove(ggblist->typing); + ggblist->typing = 0; +} + +static void +status_selection_changed(GntComboBox *box, StatusBoxItem *old, StatusBoxItem *now, gpointer null) +{ + gnt_entry_set_text(GNT_ENTRY(ggblist->statustext), NULL); + if (now->type == STATUS_SAVED) + { + /* Set the status immediately */ + gaim_savedstatus_activate(now->u.saved); + } + else if (now->type == STATUS_PRIMITIVE) + { + /* Move the focus to the entry box */ + gnt_box_move_focus(GNT_BOX(ggblist->window), 1); + ggblist->typing = g_timeout_add(TYPING_TIMEOUT, (GSourceFunc)remove_typing_cb, NULL); + } + else + g_return_if_reached(); +} + +static gboolean +status_text_changed(GntEntry *entry, const char *text, gpointer null) +{ + if (text[0] == 27 && ggblist->typing == 0) + return FALSE; + + g_source_remove(ggblist->typing); + ggblist->typing = 0; + + if (text[0] == '\r' && text[1] == 0) + { + /* Set the status only after you press 'Enter' */ + remove_typing_cb(NULL); + return TRUE; + } + + ggblist->typing = g_timeout_add(TYPING_TIMEOUT, (GSourceFunc)remove_typing_cb, NULL); + return FALSE; +} + +static void +savedstatus_changed(GaimSavedStatus *now, GaimSavedStatus *old) +{ + /* Block the signals we don't want to emit */ + GList *list; + GaimStatusPrimitive prim; + const char *message; + + if (!ggblist) + return; + + g_signal_handlers_block_matched(ggblist->status, G_SIGNAL_MATCH_FUNC, + 0, 0, NULL, status_selection_changed, NULL); + g_signal_handlers_block_matched(ggblist->statustext, G_SIGNAL_MATCH_FUNC, + 0, 0, NULL, status_text_changed, NULL); + + prim = gaim_savedstatus_get_type(now); + message = gaim_savedstatus_get_message(now); + + list = g_object_get_data(G_OBJECT(ggblist->status), "list of statuses"); + for (; list; list = list->next) + { + StatusBoxItem *item = list->data; + if (item->type == STATUS_PRIMITIVE && item->u.prim == prim) + { + gnt_combo_box_set_selected(GNT_COMBO_BOX(ggblist->status), item); + gnt_entry_set_text(GNT_ENTRY(ggblist->statustext), message); + gnt_widget_draw(ggblist->status); + break; + } + } + + g_signal_handlers_unblock_matched(ggblist->status, G_SIGNAL_MATCH_FUNC, + 0, 0, NULL, status_selection_changed, NULL); + g_signal_handlers_unblock_matched(ggblist->statustext, G_SIGNAL_MATCH_FUNC, + 0, 0, NULL, status_text_changed, NULL); +} + void gg_blist_show() { if (ggblist) @@ -805,7 +995,7 @@ gaim_get_blist()->ui_data = ggblist; - ggblist->window = gnt_box_new(FALSE, FALSE); + ggblist->window = gnt_vbox_new(FALSE); gnt_widget_set_name(ggblist->window, "buddylist"); gnt_box_set_toplevel(GNT_BOX(ggblist->window), TRUE); gnt_box_set_title(GNT_BOX(ggblist->window), _("Buddy List")); @@ -820,13 +1010,23 @@ gaim_prefs_get_int(PREF_ROOT "/position/y")); gnt_box_add_widget(GNT_BOX(ggblist->window), ggblist->tree); + + gnt_box_add_widget(GNT_BOX(ggblist->window), gnt_hline_new()); + + ggblist->status = gnt_combo_box_new(); + gnt_box_add_widget(GNT_BOX(ggblist->window), ggblist->status); + ggblist->statustext = gnt_entry_new(NULL); + gnt_box_add_widget(GNT_BOX(ggblist->window), ggblist->statustext); + + populate_status_dropdown(); + gnt_widget_show(ggblist->window); gaim_signal_connect(gaim_blist_get_handle(), "buddy-status-changed", gg_blist_get_handle(), GAIM_CALLBACK(buddy_status_changed), ggblist); gaim_signal_connect(gaim_blist_get_handle(), "buddy-idle-changed", gg_blist_get_handle(), GAIM_CALLBACK(buddy_idle_changed), ggblist); - + #if 0 gaim_signal_connect(gaim_blist_get_handle(), "buddy-signed-on", gg_blist_get_handle(), GAIM_CALLBACK(buddy_signed_on), ggblist); @@ -854,7 +1054,17 @@ g_signal_connect(G_OBJECT(ggblist->window), "position_set", G_CALLBACK(save_position_cb), NULL); g_signal_connect(G_OBJECT(ggblist->window), "destroy", G_CALLBACK(reset_blist_window), NULL); + /* Status signals */ + gaim_signal_connect(gaim_savedstatuses_get_handle(), "savedstatus-changed", gg_blist_get_handle(), + GAIM_CALLBACK(savedstatus_changed), NULL); + g_signal_connect(G_OBJECT(ggblist->status), "selection_changed", + G_CALLBACK(status_selection_changed), NULL); + g_signal_connect(G_OBJECT(ggblist->statustext), "key_pressed", + G_CALLBACK(status_text_changed), NULL); + populate_buddylist(); + + savedstatus_changed(gaim_savedstatus_get_current(), NULL); } void gg_blist_uninit()