soc.2009.vulture: 126c471f: Remove blist nodes from context menu.

gdick at soc.pidgin.im gdick at soc.pidgin.im
Fri Jul 24 18:30:54 EDT 2009


-----------------------------------------------------------------
Revision: 126c471fce73c7f92c794e2be3f72073041fb04a
Ancestor: 659a88b2b14098998b4755feac7b15ee2c9654e6
Author: gdick at soc.pidgin.im
Date: 2009-07-22T18:31:59
Branch: im.pidgin.soc.2009.vulture
URL: http://d.pidgin.im/viewmtn/revision/info/126c471fce73c7f92c794e2be3f72073041fb04a

Modified files:
        vulture/purpleblist.c vulture/purpleblist.h
        vulture/purplequeue.c vulture/purplequeue.h
        vulture/resource.h vulture/vulture-res.rc
        vulture/vultureblist.c vulture/vultureblist.h

ChangeLog: 

Remove blist nodes from context menu.

-------------- next part --------------
============================================================
--- vulture/purpleblist.c	2bc7ea663b751be35961ceb1002894ba9bc5e296
+++ vulture/purpleblist.c	b516a5fb34e9b61b21ee2ac59442445af5d1d233
@@ -35,6 +35,7 @@ static void AddCommonMenuItems(HMENU hme
 
 static BOOL ShouldShowNode(PurpleBlistNode *lpblistnode);
 static void AddCommonMenuItems(HMENU hmenu, PurpleBlistNode *lpblistnode, GList **lplpglistVMA, PurpleConnection *lpconnection, int iProtoIndex, int iExtendedIndex);
+static void DeleteBuddyFromAccount(PurpleBuddy *lpbuddy);
 
 
 
@@ -213,12 +214,20 @@ void PurpleBlistRemoveNode(PurpleBuddyLi
 
 	lpvbn = lpblistnode->ui_data;
 
-	/* This pointer is about to become invalid. */
-	lpvbn->lpblistnode = NULL;
+	EnterCriticalSection(&lpvbn->cs);
+	{
+		/* This pointer is about to become invalid. */
+		lpvbn->lpblistnode = NULL;
 
-	if(lpvbn->hti)
-		VulturePostUIMessage(VUIMSG_REMOVEBLISTNODE, lpvbn);
+		if(lpvbn->hti)
+			VulturePostUIMessage(VUIMSG_REMOVEBLISTNODE, lpvbn);
 
+		/* The parent may need to go, too. */
+		if(lpvbn->lpvbnParent && lpvbn->lpvbnParent->hti)
+			PurpleBlistUpdateNode(lpbuddylist, lpvbn->lpvbnParent->lpblistnode);
+	}
+	LeaveCriticalSection(&lpvbn->cs);
+
 	VultureBListNodeRelease((VULTURE_BLIST_NODE*)lpblistnode->ui_data);
 
 	lpblistnode->ui_data = NULL;
@@ -453,3 +462,100 @@ void PurpleBlistAliasNode(PurpleBlistNod
 
 	g_free(szAliasUTF8);
 }
+
+
+/**
+ * Removes a buddy-list from libpurple's buddy list.
+ *
+ * @param	lpblistnode	Buddy-list node.
+ */
+void PurpleDeleteBlistNode(PurpleBlistNode *lpblistnode)
+{
+	if(!lpblistnode)
+		return;
+
+	if(PURPLE_BLIST_NODE_IS_CHAT(lpblistnode))
+	{
+		/* Chats are easy, since they only exist in the buddy list and
+		 * have no children.
+		 */
+		purple_blist_remove_chat((PurpleChat*)lpblistnode);
+	}
+	else if(PURPLE_BLIST_NODE_IS_BUDDY(lpblistnode))
+	{
+		DeleteBuddyFromAccount((PurpleBuddy*)lpblistnode);
+		purple_blist_remove_buddy((PurpleBuddy*)lpblistnode);
+	}
+	else if(PURPLE_BLIST_NODE_IS_CONTACT(lpblistnode))
+	{
+		PurpleBlistNode *lpblistnodeBuddies;
+
+		/* Remove any buddies from their respective accounts. */
+		for(lpblistnodeBuddies = lpblistnode->child;
+			lpblistnodeBuddies;
+			lpblistnodeBuddies = lpblistnodeBuddies->next)
+		{
+			if(PURPLE_BLIST_NODE_IS_BUDDY(lpblistnodeBuddies))
+				DeleteBuddyFromAccount((PurpleBuddy*)lpblistnodeBuddies);
+		}
+
+		purple_blist_remove_contact((PurpleContact*)lpblistnode);
+	}
+	else if(PURPLE_BLIST_NODE_IS_GROUP(lpblistnode))
+	{
+		PurpleBlistNode *lpblistnodeInGroup = lpblistnode->child;
+
+		/* Traverse tree, deleting everything, and being careful with
+		 * the list pointers.
+		 */
+		while(lpblistnodeInGroup)
+		{
+			if(PURPLE_BLIST_NODE_IS_CONTACT(lpblistnodeInGroup))
+			{
+				PurpleContact *lpcontact = (PurpleContact*)lpblistnodeInGroup;
+				PurpleBlistNode *lpblistnodeBuddies = lpblistnode->child;
+				lpblistnodeInGroup = lpblistnodeInGroup->next;
+
+				while(lpblistnodeBuddies)
+				{
+					if(PURPLE_BLIST_NODE_IS_BUDDY(lpblistnodeBuddies))
+					{
+						PurpleBuddy *lpbuddy = (PurpleBuddy*)lpblistnodeBuddies;
+						lpblistnodeBuddies = lpblistnodeBuddies->next;
+
+						DeleteBuddyFromAccount(lpbuddy);
+						purple_blist_remove_buddy(lpbuddy);
+					}
+					else
+						lpblistnodeBuddies = lpblistnodeBuddies->next;
+				}
+
+				purple_blist_remove_contact(lpcontact);
+			}
+			else if(PURPLE_BLIST_NODE_IS_CHAT(lpblistnodeInGroup))
+			{
+				PurpleChat *lpchat = (PurpleChat*)lpblistnodeInGroup;
+				lpblistnodeInGroup = lpblistnodeInGroup->next;
+				purple_blist_remove_chat(lpchat);
+			}
+			else
+				lpblistnodeInGroup = lpblistnodeInGroup->next;
+		}
+
+		purple_blist_remove_group((PurpleGroup*)lpblistnode);
+	}
+}
+
+
+/**
+ * Removes a buddy from its account, if that account is connected.
+ *
+ * @param	lpbuddy		Buddy.
+ */
+static void DeleteBuddyFromAccount(PurpleBuddy *lpbuddy)
+{
+	PurpleAccount *lpaccount = purple_buddy_get_account(lpbuddy);
+
+	if(purple_account_is_connected(lpaccount))
+		purple_account_remove_buddy(lpaccount, lpbuddy, purple_buddy_get_group(lpbuddy));
+}
============================================================
--- vulture/purpleblist.h	af9870519752904d7644f52f1da45e3833250386
+++ vulture/purpleblist.h	a70828ebc277bb5291ce8a37f144db6f62bf2941
@@ -41,6 +41,7 @@ void PurpleBlistAliasNode(PurpleBlistNod
 void PurpleMakeBuddyMenu(HMENU hmenu, PurpleBlistNode *lpblistnode, GList **lplpglistVMA);
 void PurpleMakeChatMenu(HMENU hmenu, PurpleBlistNode *lpblistnode, GList **lplpglistVMA);
 void PurpleBlistAliasNode(PurpleBlistNode *lpblistnode, LPCTSTR szAlias);
+void PurpleDeleteBlistNode(PurpleBlistNode *lpblistnode);
 
 
 static INLINE void VultureBListNodeAddRef(VULTURE_BLIST_NODE *lpvblnode) { InterlockedIncrement(&lpvblnode->lRefCount); }
============================================================
--- vulture/purplequeue.c	7f16e6679fbaf37b6ee5dd1e38c1ef42762b4454
+++ vulture/purplequeue.c	f233b9684865dcadab89c0135eb76d10cd5d8e31
@@ -335,6 +335,18 @@ static void DispatchPurpleCall(PURPLE_CA
 
 		break;
 
+	case PC_REMOVEBLISTNODE:
+		PurpleDeleteBlistNode(((VULTURE_BLIST_NODE*)lppurplecall->lpvParam)->lpblistnode);
+		break;
+
+	case PC_BLISTNODEHASCHILDREN:
+		{
+			VULTURE_BLIST_NODE_GET_BOOL *lpvbngetbool = lppurplecall->lpvParam;
+			lpvbngetbool->bReturn = lpvbngetbool->lpvblistnode->lpblistnode && lpvbngetbool->lpvblistnode->lpblistnode->child;
+		}
+
+		break;
+
 	case PC_QUIT:
 		purple_core_quit();
 		g_main_loop_quit(g_lpgmainloop);
============================================================
--- vulture/purplequeue.h	231e847f1a6d7a374a98e035870840358a1af803
+++ vulture/purplequeue.h	1b419a9f8e73dc3f4fd4b4a5cc176df3be224f96
@@ -97,6 +97,12 @@ enum PURPLE_CALL_ID
 
 	/* (VULTURE_BLIST_NODE*) Chat node. */
 	PC_TOGGLEAUTOJOIN,
+
+	/* (VULTURE_BLIST_NODE*) */
+	PC_REMOVEBLISTNODE,
+
+	/* (VULTURE_BLIST_NODE_GET_BOOL*) */
+	PC_BLISTNODEHASCHILDREN,
 };
 
 
============================================================
--- vulture/resource.h	4f4f051631c8f2066662972e132da591c11e4354
+++ vulture/resource.h	71fba6866b61e5ef3518586cb0f28c4e6ac96f2a
@@ -68,3 +68,5 @@
 #define IDS_ACCMGR_PROTOCOL                     4
 #define IDS_ERROR_CONVCONTCLASS                 5
 #define IDS_ERROR_RICHEDIT                      6
+#define IDS_QUERY_DELGROUP                      7
+#define IDS_QUERY_DELCONTACT                    8
============================================================
--- vulture/vulture-res.rc	9c4feae7646ef2779d955bccba9eee35028dbba3
+++ vulture/vulture-res.rc	c2410c425b80bc856886f306c742534fb14f0f68
@@ -41,7 +41,7 @@ IDM_CONV MENU
 
 #define CONTEXT_ALIAS_REMOVE \
 	MENUITEM "Set &alias", IDM_BLIST_CONTEXT_ALIAS, MFT_STRING \
-	MENUITEM "&Remove from buddy list", IDM_BLIST_CONTEXT_REMOVE, MFT_STRING, MFS_GRAYED
+	MENUITEM "&Remove from buddy list", IDM_BLIST_CONTEXT_REMOVE, MFT_STRING
 
 #define BUDDY_CONTACT_COMMON \
 	MENUITEM "Start &conversation", IDM_BLIST_CONTEXT_ACTIVATE, MFT_STRING, MFS_DEFAULT \
@@ -210,6 +210,8 @@ STRINGTABLE
     IDS_ACCMGR_PROTOCOL           "Protocol"
     IDS_ERROR_CONVCONTCLASS       "Couldn't register conversation container class."
     IDS_ERROR_RICHEDIT            "Couldn't load RichEdit."
+    IDS_QUERY_DELGROUP            "Deleting this group will also delete everything contained in it. Do you wish to continue?"
+    IDS_QUERY_DELCONTACT          "Deleting this contact will also delete all buddies associated with it. Do you wish to continue?"
 }
 
 
============================================================
--- vulture/vultureblist.c	6b652e2f3614508a0df595c2dba5cdfb9f17104d
+++ vulture/vultureblist.c	def4faff462d708a6cddf8a610974a4dfbb21809
@@ -59,6 +59,7 @@ static void RunChatMenuCmd(HWND hwndBudd
 static void RunBuddyMenuCmd(HWND hwndBuddies, VULTURE_BLIST_NODE *lpvblistnode, HMENU hmenu, int iCmd);
 static BOOL RunCommonMenuCmd(HWND hwndBuddies, VULTURE_BLIST_NODE *lpvblistnode, HMENU hmenu, int iCmd);
 static void RunChatMenuCmd(HWND hwndBuddies, VULTURE_BLIST_NODE *lpvblistnode, HMENU hmenu, int iCmd);
+static void RemoveNodeRequest(HWND hwndBuddies, VULTURE_BLIST_NODE *lpvblistnode);
 
 
 #define BLIST_MARGIN 6
@@ -614,6 +615,7 @@ static INT_PTR CALLBACK BuddyListDlgProc
 							TreeView_GetItem(lpnmhdr->hwndFrom, &tvitem);
 
 							lpvblistnode = (VULTURE_BLIST_NODE*)tvitem.lParam;
+							VultureBListNodeAddRef(lpvblistnode);
 
 							/* Assume we need to ask the core for extra items. */
 							bExtraItems = TRUE;
@@ -683,6 +685,8 @@ static INT_PTR CALLBACK BuddyListDlgProc
 								}
 							}
 
+							VultureBListNodeRelease(lpvblistnode);
+
 							/* Destroy menu. This will also destroy our modifications. */
 							DestroyMenu(hmenu);
 
@@ -991,6 +995,10 @@ static BOOL RunCommonMenuCmd(HWND hwndBu
 		SendMessage(hwndBuddies, TVM_EDITLABEL, 0, (LPARAM)lpvblistnode->hti);
 		return TRUE;
 
+	case IDM_BLIST_CONTEXT_REMOVE:
+		RemoveNodeRequest(hwndBuddies, lpvblistnode);
+		return TRUE;
+
 	default:
 		/* Not a static command that we recongise; might be a dynamic
 		 * command.
@@ -1036,3 +1044,33 @@ static void RunChatMenuCmd(HWND hwndBudd
 		break;
 	}
 }
+
+
+/**
+ * Deletes a buddy-list node, prompting the user first if necessary.
+ *
+ * @param	hwndBuddies	Buddy-list tree-view.
+ * @param	lpvblistnode	List node to delete.
+ */
+static void RemoveNodeRequest(HWND hwndBuddies, VULTURE_BLIST_NODE *lpvblistnode)
+{
+	VULTURE_BLIST_NODE_GET_BOOL vblngetbool;
+	BOOL bDelete = TRUE;
+
+	vblngetbool.lpvblistnode = lpvblistnode;
+	VultureSingleSyncPurpleCall(PC_BLISTNODEHASCHILDREN, &vblngetbool);
+
+	/* If we have any children, prompt before deleting. */
+	if(vblngetbool.bReturn)
+	{
+		EnterCriticalSection(&lpvblistnode->cs);
+			if(lpvblistnode->nodetype == PURPLE_BLIST_GROUP_NODE)
+				bDelete = MessageBoxFromStringTable(g_hwndMain, IDS_QUERY_DELGROUP, MB_ICONEXCLAMATION | MB_YESNO);
+			else if(lpvblistnode->nodetype == PURPLE_BLIST_CONTACT_NODE)
+				bDelete = MessageBoxFromStringTable(g_hwndMain, IDS_QUERY_DELCONTACT, MB_ICONEXCLAMATION | MB_YESNO);
+		LeaveCriticalSection(&lpvblistnode->cs);
+	}
+
+	if(bDelete)
+		VultureSingleSyncPurpleCall(PC_REMOVEBLISTNODE, lpvblistnode);
+}
============================================================
--- vulture/vultureblist.h	677720b04ee7247e4f175ab294c5466b8b7be9c9
+++ vulture/vultureblist.h	87f6739800c61a41b79503397408ffe6fa037fac
@@ -43,11 +43,17 @@ typedef struct _VULTURE_ALIAS_NODE
 
 typedef struct _VULTURE_ALIAS_NODE
 {
-	VULTURE_BLIST_NODE *lpvblistnode;
-	LPTSTR szAlias;
+	VULTURE_BLIST_NODE	*lpvblistnode;
+	LPTSTR			szAlias;
 } VULTURE_ALIAS_NODE;
 
+typedef struct _VULTURE_BLIST_NODE_GET_BOOL
+{
+	VULTURE_BLIST_NODE	*lpvblistnode;
+	BOOL			bReturn;
+} VULTURE_BLIST_NODE_GET_BOOL;
 
+
 extern HWND g_hwndMain;
 GList *g_lpglistConvContainers;
 


More information about the Commits mailing list