src/buddy.c

changeset 4916
11b8fd3f8ffc
parent 4912
eb8098c7f102
child 4918
0600d084c97a
--- a/src/buddy.c	Mon Mar 31 02:38:44 2003 +0000
+++ b/src/buddy.c	Mon Mar 31 07:19:46 2003 +0000
@@ -165,7 +165,7 @@
 
 static void gtk_blist_show_onlinehelp_cb()
 {
-       open_url(NULL, "http://gaim.sourceforge.net/documentation.php");
+       open_url(NULL, WEBSITE "documentation.php");
 }
 
 static void gtk_blist_button_im_cb(GtkWidget *w, GtkTreeView *tv)
@@ -239,6 +239,35 @@
 	}
 }
 
+static void gaim_gtk_blist_add_buddy_cb()
+{
+	GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gtkblist->treeview));
+	GtkTreeIter iter;
+	GaimBlistNode *node;
+
+	if(gtk_tree_selection_get_selected(sel, NULL, &iter)){
+		gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1);
+		if (GAIM_BLIST_NODE_IS_BUDDY(node)) 
+			show_add_buddy(NULL, NULL, ((struct group*)node->parent)->name, NULL);
+		else if (GAIM_BLIST_NODE_IS_GROUP(node))
+			show_add_buddy(NULL, NULL, ((struct group*)node)->name, NULL);
+	}
+	else {
+		show_add_buddy(NULL, NULL, NULL, NULL);
+	}
+}
+
+gaim_gtk_blist_remove_cb (GtkWidget *w, GaimBlistNode *node) 
+{
+	if (GAIM_BLIST_NODE_IS_BUDDY(node)) {
+		struct buddy *b = (struct buddy*)node;
+		show_confirm_del(b->account->gc, b->name);
+	} else if (GAIM_BLIST_NODE_IS_GROUP(node)) {
+		struct group *g = (struct group*)node;
+		show_confirm_del_group(g);
+	}
+}
+
 static void gaim_proto_menu_cb(GtkMenuItem *item, struct buddy *b)
 {
 	struct proto_buddy_menu *pbm = g_object_get_data(G_OBJECT(item), "gaimcallback");
@@ -267,53 +296,74 @@
 	gtk_tree_model_get_iter(GTK_TREE_MODEL(gtkblist->treemodel), &iter, path);
 	gtk_tree_model_get_value (GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &val);
 	node = g_value_get_pointer(&val);
-
-	if (!GAIM_BLIST_NODE_IS_BUDDY(node)) {
-		gtk_tree_path_free(path);
-		return FALSE;
-	}
-
 	menu = gtk_menu_new();
 
-	/* Protocol specific options */
-	prpl = find_prpl(((struct buddy*)node)->account->protocol);
+	if (GAIM_BLIST_NODE_IS_GROUP(node)) {
+		menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Add a Buddy"));
+		g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gaim_gtk_blist_add_buddy_cb), node);
+		image = gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_MENU);
+		gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
+		gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+		
+		menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Delete Group"));
+		g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gaim_gtk_blist_remove_cb), node);
+		image = gtk_image_new_from_stock(GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU);
+		gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
+		gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+
+		menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Rename"));
+		g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(show_rename_group), node);
+		gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+	} else if (GAIM_BLIST_NODE_IS_BUDDY(node)) {
+		
+		/* Protocol specific options */
+		prpl = find_prpl(((struct buddy*)node)->account->protocol);
+
+		if(prpl && prpl->get_info) {
+			menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Get Info"));
+			g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_blist_menu_info_cb), node);
+			gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+		}
 
-	if(prpl && prpl->get_info) {
-		menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Get Info"));
-		g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_blist_menu_info_cb), node);
+		menuitem = gtk_image_menu_item_new_with_mnemonic(_("_IM"));
+		g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_blist_menu_im_cb), node);
+		image = gtk_image_new_from_stock(GAIM_STOCK_IM, GTK_ICON_SIZE_MENU);
+		gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
+		gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+
+		menuitem = gtk_image_menu_item_new_with_mnemonic(_("Add Buddy _Pounce"));
+		g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_blist_menu_bp_cb), node);
+		gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+
+		menuitem = gtk_image_menu_item_new_with_mnemonic(_("View _Log"));
+		g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_blist_menu_showlog_cb), node);
+		gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+
+		if (prpl) {
+			list = prpl->buddy_menu(((struct buddy*)node)->account->gc, ((struct buddy*)node)->name);
+			while (list) {
+				struct proto_buddy_menu *pbm = list->data;
+				menuitem = gtk_menu_item_new_with_mnemonic(pbm->label);
+				g_object_set_data(G_OBJECT(menuitem), "gaimcallback", pbm);
+				g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gaim_proto_menu_cb), node);
+				gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+				list = list->next;
+			}
+		}
+	
+		gaim_separator(menu);
+	
+		menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Alias"));
+		g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_blist_menu_alias_cb), node);
+		gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
+
+		menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Remove"));
+		g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gaim_gtk_blist_remove_cb), node);
+		image = gtk_image_new_from_stock(GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU);
+		gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
 		gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
 	}
-
-	menuitem = gtk_image_menu_item_new_with_mnemonic(_("_IM"));
-	g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_blist_menu_im_cb), node);
-	image = gtk_image_new_from_stock(GAIM_STOCK_IM, GTK_ICON_SIZE_MENU);
-	gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menuitem), image);
-	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
-
-	menuitem = gtk_image_menu_item_new_with_mnemonic(_("_Alias"));
-	g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_blist_menu_alias_cb), node);
-	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
-
-	menuitem = gtk_image_menu_item_new_with_mnemonic(_("Add Buddy _Pounce"));
-	g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_blist_menu_bp_cb), node);
-	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
-
-	menuitem = gtk_image_menu_item_new_with_mnemonic(_("View _Log"));
-	g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gtk_blist_menu_showlog_cb), node);
-	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
-
-	if (prpl) {
-		list = prpl->buddy_menu(((struct buddy*)node)->account->gc, ((struct buddy*)node)->name);
-		while (list) {
-			struct proto_buddy_menu *pbm = list->data;
-			menuitem = gtk_menu_item_new_with_mnemonic(pbm->label);
-			g_object_set_data(G_OBJECT(menuitem), "gaimcallback", pbm);
-			g_signal_connect(G_OBJECT(menuitem), "activate", G_CALLBACK(gaim_proto_menu_cb), node);
-			gtk_menu_shell_append(GTK_MENU_SHELL(menu), menuitem);
-			list = list->next;
-		}
-	}
-
+	
 	gtk_widget_show_all(menu);
 	
 	gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 3, event->time);
@@ -336,24 +386,19 @@
 	gaim_gtk_blist_update(NULL, b);
 	return FALSE;
 }
-
-static void gaim_gtk_blist_add_buddy_cb()
-{
-	GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(gtkblist->treeview));
-	GtkTreeIter iter;
-	GaimBlistNode *node;
+static void edit_mode_cb() {
+	GdkCursor *cursor = gdk_cursor_new(GDK_WATCH);
+	gdk_window_set_cursor(gtkblist->window->window, cursor);
+	while (gtk_events_pending())
+		gtk_main_iteration();
+	gtkblist->editmode = !gtkblist->editmode;
+	gdk_cursor_unref(cursor);
+	cursor = gdk_cursor_new(GDK_LEFT_PTR);
+	gdk_window_set_cursor(gtkblist->window->window, cursor);
+	gdk_cursor_unref(cursor);
+	gaim_gtk_blist_refresh(gaim_get_blist());
+}
 
-	if(gtk_tree_selection_get_selected(sel, NULL, &iter)){
-		gtk_tree_model_get(GTK_TREE_MODEL(gtkblist->treemodel), &iter, NODE_COLUMN, &node, -1);
-		if (GAIM_BLIST_NODE_IS_BUDDY(node)) 
-			show_add_buddy(NULL, NULL, ((struct group*)node->parent)->name, NULL);
-		else if (GAIM_BLIST_NODE_IS_GROUP(node))
-			show_add_buddy(NULL, NULL, ((struct group*)node)->name, NULL);
-	}
-	else {
-		show_add_buddy(NULL, NULL, NULL, NULL);
-	}
-}
 
 static void gaim_gtk_blist_update_toolbar_icons (GtkWidget *widget, gpointer data) {
 	if (GTK_IS_IMAGE(widget)) {
@@ -592,9 +637,7 @@
 {
 	/* Buddies menu */
 	{ N_("/_Buddies"), NULL, NULL, 0, "<Branch>" },
-	{ N_("/Buddies/_Add A Buddy..."), "<CTL>B", gaim_gtk_blist_add_buddy_cb, 0,
-	  "<StockItem>", GTK_STOCK_ADD },
-	{ N_("/Buddies/New _Instant Message..."), "<CTL>I", show_im_dialog, 0,
+		{ N_("/Buddies/New _Instant Message..."), "<CTL>I", show_im_dialog, 0,
 	  "<StockItem>", GAIM_STOCK_IM },
 	{ N_("/Buddies/Join a _Chat..."), "<CTL>C", join_chat, 0, 
 	  "<StockItem>", GAIM_STOCK_CHAT },
@@ -606,19 +649,27 @@
 	{ N_("/Buddies/_Quit"), "<CTL>Q", do_quit, 0,
 	  "<StockItem>", GTK_STOCK_QUIT },
 
+	/* Edit menu */
+	{ N_("/_Edit"), NULL, NULL, 0, "<Branch>" },
+	{ N_("/Edit/_Show Offline Buddies"), NULL, edit_mode_cb, 0, "<CheckItem>"},
+	{ N_("/Edit/_Add a Buddy..."), NULL, gaim_gtk_blist_add_buddy_cb, 0, "<StockItem>", GTK_STOCK_ADD }, 
+	{ N_("/Edit/Add a _Group..."), NULL, show_add_group, 0, NULL},
+	{ "/Edit/sep", NULL, NULL, 0, "<Separator>" },
+	{ N_("/Edit/A_ccounts"), "<CTL>A", account_editor, 0, NULL },
+	{ N_("/Edit/Preferences"), "<CTL>P", show_prefs, 0,
+	  "<StockItem>", GTK_STOCK_PREFERENCES },
+	{ N_("/Edit/Pr_ivacy"), NULL, show_privacy_options, 0, NULL },
+	
+
 	/* Tools */ 
 	{ N_("/_Tools"), NULL, NULL, 0, "<Branch>" },
 	{ N_("/Tools/_Away"), NULL, NULL, 0, "<Branch>" },
 	{ N_("/Tools/Buddy _Pounce"), NULL, NULL, 0, "<Branch>" },
-	{ "/Tools/sep1", NULL, NULL, 0, "<Separator>" },
-	{ N_("/Tools/A_ccounts"), "<CTL>A", account_editor, 0, NULL },
-	{ N_("/Tools/Preferences"), "<CTL>P", show_prefs, 0,
-	  "<StockItem>", GTK_STOCK_PREFERENCES },
+	{ N_("/Tools/sep1"), NULL, NULL, 0, "<Separator>" },
 	{ N_("/Tools/_File Transfers"), NULL, gaim_show_xfer_dialog, 0,
 	  "<StockItem>", GTK_STOCK_REVERT_TO_SAVED },
 	{ "/Tools/sep2", NULL, NULL, 0, "<Separator>" },
 	{ N_("/Tools/P_rotocol Actions"), NULL, NULL, 0, "<Branch>" },
-	{ N_("/Tools/Pr_ivacy"), NULL, show_privacy_options, 0, NULL },
 	{ N_("/Tools/View System _Log"), NULL, gtk_blist_show_systemlog_cb, 0, NULL },
 
 	/* Help */
@@ -680,12 +731,14 @@
 			       "%s %s"  /* Nickname */
 			       "%s %s"     /* Idle */
 			       "%s %s"     /* Warning */
+			       "%s"        /* Offline */
 			       "%s%s",    /* Status */
 			       b->name,
 			       aliastext ? _("\n<b>Alias:</b>") : "", aliastext ? aliastext : "",
 			       nicktext ? _("\n<b>Nickname:</b>") : "", nicktext ? nicktext : "",
 			       b->idle ? _("\n<b>Idle:</b>") : "", b->idle ? idletime : "",
 			       b->evil ? _("\n<b>Warned:</b>") : "", b->evil ? warning : "",
+			       !b->present ? _("\n<b>Status:</b> Offline") : "",
 			       statustext ? "\n" : "", statustext ? statustext : "");
 	if(warning)
 		g_free(warning);
@@ -715,11 +768,15 @@
 	int scalesize = 30;
 
 	struct prpl* prpl = find_prpl(b->account->protocol);
+
+	if (!prpl) 
+		return NULL;
+
 	if (prpl->list_icon)
 		protoname = prpl->list_icon(b->account, b);
 	if (prpl->list_emblems)
 		prpl->list_emblems(b, &se, &sw, &nw, &ne);
-
+	
 	if (size == GAIM_STATUS_ICON_SMALL) {
 		scalesize = 15;
 		sw = nw = ne = NULL; /* So that only the se icon will composite */
@@ -842,7 +899,7 @@
 
 
 	/* Idle grey buddies affects the whole row.  This converts the status icon to greyscale. */
-	if (b->idle && blist_options & OPT_BLIST_GREY_IDLERS)
+	if ((b->idle && blist_options & OPT_BLIST_GREY_IDLERS) || gtkblist->editmode)
 		gdk_pixbuf_saturate_and_pixelate(scale, scale, 0, FALSE);
 	return scale;
 }
@@ -864,7 +921,7 @@
 
 
 	if (buf) {
-		if (b->idle && blist_options & OPT_BLIST_GREY_IDLERS) {
+		if ((b->idle && blist_options & OPT_BLIST_GREY_IDLERS) || gtkblist->editmode) {
 			gdk_pixbuf_saturate_and_pixelate(buf, buf, 0, FALSE);
 		}
 		ret = gdk_pixbuf_scale_simple(buf,30,30, GDK_INTERP_BILINEAR);
@@ -887,7 +944,7 @@
 	time_t t;
 
 	if (!(blist_options & OPT_BLIST_SHOW_ICONS)) {
-		if (b->idle > 0 && blist_options & OPT_BLIST_GREY_IDLERS && !selected) {
+		if ((b->idle > 0 && blist_options & OPT_BLIST_GREY_IDLERS && !selected) || gtkblist->editmode) {
 			text =  g_strdup_printf("<span color='dim grey'>%s</span>",
 						esc);
 			g_free(esc);
@@ -901,7 +958,7 @@
 	ihrs = (t - b->idle) / 3600;
 	imin = ((t - b->idle) / 60) % 60;
 
-	if (prpl->status_text) {
+	if (prpl && prpl->status_text) {
 		char *tmp = prpl->status_text(b);
 		const char *end;
 
@@ -952,19 +1009,23 @@
 		warning = g_strdup_printf(_("Warned (%d%%) "), b->evil);
 
 	if (b->idle && blist_options & OPT_BLIST_GREY_IDLERS && !selected) {
-		text =  g_strdup_printf("<span color='dim grey'>%s</span>\n<span color='dim grey' size='smaller'>%s%s%s</span>",
+		text =  g_strdup_printf("<span color='dim grey'>%s</span>\n"
+					"<span color='dim grey' size='smaller'>%s%s%s%s</span>",
 					esc,
 					statustext != NULL ? statustext : "",
 					idletime != NULL ? idletime : "", 
-					warning != NULL ? warning : "");
-	} else if (statustext == NULL && idletime == NULL && warning == NULL) {
-		text = g_strdup_printf("%s", esc);
+					warning != NULL ? warning : "",
+					!b->present ? _("Offline ") : "");
+	} else if (statustext == NULL && idletime == NULL && warning == NULL && b->present) {
+		text = g_strdup(esc);
 	} else {
-		text = g_strdup_printf("%s\n<span %s size='smaller'>%s%s%s</span>", esc,
-				selected ? "" : "color='dim grey'",
-				statustext != NULL ? statustext :  "",
-				idletime != NULL ? idletime : "", 
-				warning != NULL ? warning : "");
+		text = g_strdup_printf("%s\n"
+				       "<span %s size='smaller'>%s%s%s%s</span>", esc,
+				       selected ? "" : "color='dim grey'",
+				       statustext != NULL ? statustext :  "",
+				       idletime != NULL ? idletime : "", 
+				       warning != NULL ? warning : "",
+				       !b->present ? _("Offline ") : "");
 	}
 	if (idletime)
 		g_free(idletime);
@@ -1097,6 +1158,7 @@
 						 G_TYPE_STRING, G_TYPE_STRING, GDK_TYPE_PIXBUF, G_TYPE_POINTER);
 
 	gtkblist->treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(gtkblist->treemodel));
+	gtk_widget_set_size_request(gtkblist->treeview, -1, 200);
 
 	/* Set up selection stuff */
 
@@ -1195,8 +1257,8 @@
 	GaimBlistNode *buddy;
 
 	while (group) {
+		buddy = group->child;
 		gaim_gtk_blist_update(list, group);
-		buddy = group->child;
 		while (buddy) {
 			gaim_gtk_blist_update(list, buddy);
 			buddy = buddy->next;
@@ -1327,7 +1389,7 @@
 	if (!get_iter_from_node(node, &iter)) { /* This is a newly added node */
 		new_entry = TRUE;
 		if (GAIM_BLIST_NODE_IS_BUDDY(node)) {
-			if (((struct buddy*)node)->present) {
+			if (((struct buddy*)node)->present || (gtkblist->editmode && ((struct buddy*)node)->account->gc)) {
 				GtkTreeIter groupiter;
 				GaimBlistNode *oldersibling;
 				GtkTreeIter oldersiblingiter;
@@ -1377,9 +1439,44 @@
 				}
 			}
 		}
+		else if (GAIM_BLIST_NODE_IS_GROUP(node) && gtkblist->editmode) {
+			GaimBlistNode *oldersibling;
+			GtkTreeIter oldersiblingiter;
+			GdkPixbuf *groupicon = gtk_widget_render_icon(gtkblist->treeview,
+								      GTK_STOCK_OPEN, GTK_ICON_SIZE_SMALL_TOOLBAR, NULL);
+			char *esc = g_markup_escape_text(((struct group*)node)->name, -1);
+			char *mark = g_strdup_printf("<span weight='bold'>%s</span>", esc);
+			g_free(esc);
+			oldersibling = node->prev;
+			while (oldersibling && !get_iter_from_node(oldersibling, &oldersiblingiter)) {
+				oldersibling = oldersibling->prev;
+			}
+			
+			gtk_tree_store_insert_after(gtkblist->treemodel, &iter, NULL, oldersibling ? &oldersiblingiter : NULL);
+			gtk_tree_store_set(gtkblist->treemodel, &iter,
+					   STATUS_ICON_COLUMN, groupicon,
+					   NAME_COLUMN, mark,
+					   NODE_COLUMN, node,
+					   -1);
+			g_free(mark);
+			g_object_unref(groupicon);
+		}
+		
+	} else if (GAIM_BLIST_NODE_IS_GROUP(node)) {
+			if (gtk_tree_model_iter_has_child(GTK_TREE_MODEL(gtkblist->treemodel), &iter) == FALSE && gtkblist->editmode == FALSE)
+			gtk_tree_store_remove(gtkblist->treemodel, &iter);
+		else {
+			char *esc = g_markup_escape_text(((struct group*)node)->name, -1);
+			char *mark = g_strdup_printf("<span weight='bold'>%s</span>", esc);
+			g_free(esc);
+			gtk_tree_store_set(gtkblist->treemodel, &iter,
+					   NAME_COLUMN, mark,
+					   -1);
+			g_free(mark);
+		}
 	}
 
-	if (GAIM_BLIST_NODE_IS_BUDDY(node) && ((struct buddy*)node)->present) {
+	if (GAIM_BLIST_NODE_IS_BUDDY(node) && (((struct buddy*)node)->present || (gtkblist->editmode && ((struct buddy*)node)->account->gc))) {
 		GdkPixbuf *status, *avatar;
 		char *mark;
 		char *warning = NULL, *idle = NULL;
@@ -1456,8 +1553,9 @@
 			gaim_gtk_blist_update(list, afsad);
 			afsad = afsad->next;
 		}
+		
+		gtk_tree_view_columns_autosize(GTK_TREE_VIEW(gtkblist->treeview));
 	}
-	gtk_tree_view_columns_autosize(GTK_TREE_VIEW(gtkblist->treeview));
 }
 
 static void gaim_gtk_blist_destroy(struct gaim_buddy_list *list)

mercurial