adium-1.4 3030:e7b6ca0c6fbc: Removing spurious debug logging

commits at adium.im commits at adium.im
Sun Sep 19 21:04:25 UTC 2010


details:	http://hg.adium.im/adium-1.4/rev/e7b6ca0c6fbc
revision:	3030:e7b6ca0c6fbc
author:		Evan Schoenberg
date:		Sun Sep 19 15:54:07 2010 -0500

Removing spurious debug logging
Subject: adium-1.4 3031:9aed283a5ddd: Useful debug logging

details:	http://hg.adium.im/adium-1.4/rev/9aed283a5ddd
revision:	3031:9aed283a5ddd
author:		Evan Schoenberg
date:		Sun Sep 19 15:54:28 2010 -0500

Useful debug logging
Subject: adium-1.4 3032:16aedee3a0cb: Improve debug logging

details:	http://hg.adium.im/adium-1.4/rev/16aedee3a0cb
revision:	3032:16aedee3a0cb
author:		Evan Schoenberg
date:		Sun Sep 19 15:54:50 2010 -0500

Improve debug logging
Subject: adium-1.4 3033:0b981d5c2c76: Fixed multiple bugs with meta contact inter-group movement, merging of contacts,  unmerging of contacts, and determination of 'uniqueness' of metacontacts (that is, whether they are presented to the user as a single contact or as the root of a combined contact) after contacts are added or removed from a metacontact.

details:	http://hg.adium.im/adium-1.4/rev/0b981d5c2c76
revision:	3033:0b981d5c2c76
author:		Evan Schoenberg
date:		Sun Sep 19 15:58:44 2010 -0500

Fixed multiple bugs with meta contact inter-group movement, merging of contacts,  unmerging of contacts, and determination of 'uniqueness' of metacontacts (that is, whether they are presented to the user as a single contact or as the root of a combined contact) after contacts are added or removed from a metacontact.

Fixes #13965. Fixes #12156.

Other contact list issues might also be fixed in the process, since as we often hide that a contact is a metacontact (via 'uniqueness') users may report problems with non-metacontacts which are actually metacontact bugs. Refs #13871. Refs #13889.
Subject: adium-1.4 3034:dc404cfe09ca: Some cleanup, and reduced spamming of the IdleSince preference when we remain idle; previously, this was being written out every few seconds while were idle.

details:	http://hg.adium.im/adium-1.4/rev/dc404cfe09ca
revision:	3034:dc404cfe09ca
author:		Evan Schoenberg
date:		Sun Sep 19 15:59:50 2010 -0500

Some cleanup, and reduced spamming of the IdleSince preference when we remain idle; previously, this was being written out every few seconds while were idle.
Subject: adium-1.4 3035:057e7349f628: Whitespace fix

details:	http://hg.adium.im/adium-1.4/rev/057e7349f628
revision:	3035:057e7349f628
author:		Evan Schoenberg
date:		Sun Sep 19 16:00:02 2010 -0500

Whitespace fix
Subject: adium-1.4 3036:50984fdcc64d: Deloggification

details:	http://hg.adium.im/adium-1.4/rev/50984fdcc64d
revision:	3036:50984fdcc64d
author:		Evan Schoenberg
date:		Sun Sep 19 16:00:13 2010 -0500

Deloggification
Subject: adium-1.4 3037:bd2cd2a48aeb: Deloggification

details:	http://hg.adium.im/adium-1.4/rev/bd2cd2a48aeb
revision:	3037:bd2cd2a48aeb
author:		Evan Schoenberg
date:		Sun Sep 19 16:00:22 2010 -0500

Deloggification
Subject: adium-1.4 3038:19722a7790df: Don't waste memory and CPU allocating and storing the final debug messages if debug logging isn't enabled. AILog() still isn't free since any functions and methods passed as arguments are resolved, but I think this is a reasonable compromise which still lets us instruct users to enable debug logging within release builds.

details:	http://hg.adium.im/adium-1.4/rev/19722a7790df
revision:	3038:19722a7790df
author:		Evan Schoenberg
date:		Sun Sep 19 16:01:38 2010 -0500

Don't waste memory and CPU allocating and storing the final debug messages if debug logging isn't enabled. AILog() still isn't free since any functions and methods passed as arguments are resolved, but I think this is a reasonable compromise which still lets us instruct users to enable debug logging within release builds.
Subject: adium-1.4 3039:ff2202a84a35: If a contact was previously associated with an address book entry but now is not - e.g. the contact was within a metacontact that has an AB card, then is moved out of that metacontact and now should not have that same data - be sure to clear it. Also, added a debug log when grouping contacts via the address book to help investigate #13872. Refs #13872

details:	http://hg.adium.im/adium-1.4/rev/ff2202a84a35
revision:	3039:ff2202a84a35
author:		Evan Schoenberg
date:		Sun Sep 19 16:04:07 2010 -0500

If a contact was previously associated with an address book entry but now is not - e.g. the contact was within a metacontact that has an AB card, then is moved out of that metacontact and now should not have that same data - be sure to clear it. Also, added a debug log when grouping contacts via the address book to help investigate #13872. Refs #13872

diffs (788 lines):

diff -r fac84dd8c6f6 -r ff2202a84a35 Frameworks/Adium Framework/Source/AIAddressBookController.m
--- a/Frameworks/Adium Framework/Source/AIAddressBookController.m	Sun Sep 19 03:40:49 2010 +0200
+++ b/Frameworks/Adium Framework/Source/AIAddressBookController.m	Sun Sep 19 16:04:07 2010 -0500
@@ -274,54 +274,32 @@
     if (inModifiedKeys == nil) { //Only perform this when updating for all list objects or when a contact is created
         ABPerson *person = [listContact addressBookPerson];
 
-		if (person) {
-			if (enableImport) {
-				//Load the name if appropriate
-				AIMutableOwnerArray *displayNameArray, *phoneticNameArray;
-				NSString			*displayName, *phoneticName = nil;
-				
-				displayNameArray = [listContact displayArrayForKey:@"Display Name"];
-				
-				displayName = [self nameForPerson:person phonetic:&phoneticName];
+		if (person && enableImport) {
+			//Load the name if appropriate
+			AIMutableOwnerArray *displayNameArray, *phoneticNameArray;
+			NSString			*displayName, *phoneticName = nil;
+			
+			displayNameArray = [listContact displayArrayForKey:@"Display Name"];
+			
+			displayName = [self nameForPerson:person phonetic:&phoneticName];
+			
+			//Apply the values 
+			NSString *oldValue = [displayNameArray objectWithOwner:self];
+			if (!oldValue || ![oldValue isEqualToString:displayName]) {
+				[displayNameArray setObject:displayName withOwner:self];
+				modifiedAttributes = [NSSet setWithObject:@"Display Name"];
+			}
+			
+			if (phoneticName) {
+				phoneticNameArray = [listContact displayArrayForKey:@"Phonetic Name"];
 				
 				//Apply the values 
-				NSString *oldValue = [displayNameArray objectWithOwner:self];
-				if (!oldValue || ![oldValue isEqualToString:displayName]) {
-					[displayNameArray setObject:displayName withOwner:self];
-					modifiedAttributes = [NSSet setWithObject:@"Display Name"];
+				oldValue = [phoneticNameArray objectWithOwner:self];
+				if (!oldValue || ![oldValue isEqualToString:phoneticName]) {
+					[phoneticNameArray setObject:phoneticName withOwner:self];
+					modifiedAttributes = [NSSet setWithObjects:@"Display Name", @"Phonetic Name", nil];
 				}
-				
-				if (phoneticName) {
-					phoneticNameArray = [listContact displayArrayForKey:@"Phonetic Name"];
-
-					//Apply the values 
-					oldValue = [phoneticNameArray objectWithOwner:self];
-					if (!oldValue || ![oldValue isEqualToString:phoneticName]) {
-						[phoneticNameArray setObject:phoneticName withOwner:self];
-						modifiedAttributes = [NSSet setWithObjects:@"Display Name", @"Phonetic Name", nil];
-					}
-				} else {
-					phoneticNameArray = [listContact displayArrayForKey:@"Phonetic Name"
-																 create:NO];
-					//Clear any stored value
-					if ([phoneticNameArray objectWithOwner:self]) {
-						[displayNameArray setObject:nil withOwner:self];
-						modifiedAttributes = [NSSet setWithObjects:@"Display Name", @"Phonetic Name", nil];
-					}					
-				}
-
 			} else {
-				AIMutableOwnerArray *displayNameArray, *phoneticNameArray;
-				
-				displayNameArray = [listContact displayArrayForKey:@"Display Name"
-															create:NO];
-
-				//Clear any stored value
-				if ([displayNameArray objectWithOwner:self]) {
-					[displayNameArray setObject:nil withOwner:self];
-					modifiedAttributes = [NSSet setWithObject:@"Display Name"];
-				}
-				
 				phoneticNameArray = [listContact displayArrayForKey:@"Phonetic Name"
 															 create:NO];
 				//Clear any stored value
@@ -329,21 +307,46 @@
 					[displayNameArray setObject:nil withOwner:self];
 					modifiedAttributes = [NSSet setWithObjects:@"Display Name", @"Phonetic Name", nil];
 				}					
-				
 			}
-
-			//If we changed anything, request an update of the alias / long display name
-			if (modifiedAttributes) {
-				[[NSNotificationCenter defaultCenter] postNotificationName:Contact_ApplyDisplayName
-														  object:listContact
-														userInfo:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:silent]
-																							 forKey:@"Notify"]];
+			
+		} else {
+			AIMutableOwnerArray *displayNameArray, *phoneticNameArray;
+			
+			displayNameArray = [listContact displayArrayForKey:@"Display Name"
+														create:NO];
+			
+			//Clear any stored value
+			if ([displayNameArray objectWithOwner:self]) {
+				[displayNameArray setObject:nil withOwner:self];
+				modifiedAttributes = [NSSet setWithObject:@"Display Name"];
 			}
-
-			//Add this contact to the ABPerson's metacontact if it's not already there.
+			
+			phoneticNameArray = [listContact displayArrayForKey:@"Phonetic Name"
+														 create:NO];
+			//Clear any stored value
+			if ([phoneticNameArray objectWithOwner:self]) {
+				[phoneticNameArray setObject:nil withOwner:self];
+				modifiedAttributes = [NSSet setWithObjects:@"Display Name", @"Phonetic Name", nil];
+			}					
+			
+		}
+		
+		//If we changed anything, request an update of the alias / long display name
+		if (modifiedAttributes) {
+			[[NSNotificationCenter defaultCenter] postNotificationName:Contact_ApplyDisplayName
+																object:listContact
+															  userInfo:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:silent]
+																								   forKey:@"Notify"]];
+		}
+		
+		//Add this contact to the ABPerson's metacontact if it's not already there.
+		if (person) {
 			AIMetaContact *personMetaContact;
 			if ((personMetaContact = [personUniqueIdToMetaContactDict objectForKey:[person uniqueId]]) &&
+				(personMetaContact != listContact) &&
 				![personMetaContact containsObject:listContact]) {
+				AILog(@"AIAddressBookController: personMetaContact = %@; listContact = %@; performing metacontact grouping",
+					  personMetaContact, listContact);
 				[adium.contactController groupContacts:[NSArray arrayWithObjects:personMetaContact, listContact, nil]];
 			}
 		}
diff -r fac84dd8c6f6 -r ff2202a84a35 Frameworks/Adium Framework/Source/AIListContact.m
--- a/Frameworks/Adium Framework/Source/AIListContact.m	Sun Sep 19 03:40:49 2010 +0200
+++ b/Frameworks/Adium Framework/Source/AIListContact.m	Sun Sep 19 16:04:07 2010 -0500
@@ -257,8 +257,6 @@
 	BOOL changes = NO;
 	BOOL displayNameChanges = NO;
 	
-	AILogWithSignature(@"%@ received alias %@", self, alias);
-	
 	//This is the server display name.  Set it as such.
 	if (![alias isEqualToString:[self valueForProperty:@"Server Display Name"]]) {
 		//Set the server display name property as the full display name
@@ -713,6 +711,8 @@
 - (void) setMetaContact:(AIMetaContact *)meta
 {
 	metaContact = meta;
+	
+	/* Ugly: Subclass accessing superclass's ivar */
 	[m_groups removeAllObjects];
 }
 
diff -r fac84dd8c6f6 -r ff2202a84a35 Frameworks/Adium Framework/Source/AIMetaContact.h
--- a/Frameworks/Adium Framework/Source/AIMetaContact.h	Sun Sep 19 03:40:49 2010 +0200
+++ b/Frameworks/Adium Framework/Source/AIMetaContact.h	Sun Sep 19 16:04:07 2010 -0500
@@ -26,7 +26,6 @@
 	NSArray				*_listContactsIncludingOfflineAccounts;
 	
 	BOOL								containsOnlyOneUniqueContact;
-	BOOL								containsOnlyOneService;
 
 	NSMutableArray	*_containedObjects;			//Manually ordered array of contents
 	BOOL								containedObjectsNeedsSort;
diff -r fac84dd8c6f6 -r ff2202a84a35 Frameworks/Adium Framework/Source/AIMetaContact.m
--- a/Frameworks/Adium Framework/Source/AIMetaContact.m	Sun Sep 19 03:40:49 2010 +0200
+++ b/Frameworks/Adium Framework/Source/AIMetaContact.m	Sun Sep 19 16:04:07 2010 -0500
@@ -30,6 +30,10 @@
 
 #define	OBJECT_STATUS_CACHE			@"Object Status Cache"
 
+/* If META_TYPE_DEBUG is defined, metaContacts and uniqueMetaContacts are given an 
+ * identifying suffix to their formattedUID in the contact list */
+//#define META_TYPE_DEBUG TRUE
+
 @interface AIListContact ()
 @property (readwrite, nonatomic, assign) AIMetaContact *metaContact;
 - (void)setContainingObject:(AIListGroup *)inGroup;
@@ -63,8 +67,7 @@
 		
 		expanded = [[self preferenceForKey:KEY_EXPANDED group:OBJECT_STATUS_CACHE] boolValue];
 
-		containsOnlyOneUniqueContact = NO;
-		containsOnlyOneService = YES;
+		containsOnlyOneUniqueContact = YES; /* Default to YES, because addObject: will change us to NO when needed */
 		containedObjectsNeedsSort = NO;
 		saveGroupingChanges = YES;
 	}
@@ -151,7 +154,8 @@
 		[targetGroups addObject:adium.contactController.contactList];
 	}
 
-	[adium.contactController _moveContactLocally:self fromGroups:self.groups toGroups:targetGroups];
+	if (self.groups.count || targetGroups.count)
+		[adium.contactController _moveContactLocally:self fromGroups:self.groups toGroups:targetGroups];
 }
 
 - (void)removeFromGroup:(AIListObject <AIContainingObject> *)group
@@ -275,6 +279,8 @@
 		[self visibleListContacts];
 
 		success = YES;
+	} else {
+		AILogWithSignature(@"%@ (meta=%p) already contained in %@", inObject, ((AIListContact *)inObject).metaContact, self);
 	}
 	
 	return success;
@@ -285,26 +291,32 @@
  *
  * Should only be called by AIContactController.
  */
-- (void)removeObject:(AIListObject *)inObject
+- (BOOL)removeObject:(AIListObject *)inObject
 {
 	NSParameterAssert([inObject isKindOfClass:[AIListContact class]]);
 	AIListContact *contact = (AIListContact *)inObject;
 	if ([self.containedObjects containsObjectIdenticalTo:inObject]) {
-		BOOL	noteRemoteGroupingChanged = NO;
+		BOOL	needToResetToRemoteGroup = NO;
 
 		[inObject retain];
 
-		BOOL	wasPreferredContact = inObject == self.preferredContact;
+		BOOL	wasPreferredContact = (inObject == self.preferredContact);
 
 		[_containedObjects removeObject:inObject];
 		
-		if (contact.countOfRemoteGroupNames > 0) {
-			//Reset it to its remote group
+		if (contact.metaContact == self) {
+			/* If the contact is being reassigned to another metaContact, this may already have been done; we shouldn't
+			 * mess with it if it's not still ours to order around. The other metaContact will manage it as needed.
+			 */
 			contact.metaContact = nil;
-			noteRemoteGroupingChanged = YES;
-		} else {
-			for (AIListGroup *group in self.groups)
-				[contact addContainingGroup:group];
+			
+			if (contact.countOfRemoteGroupNames > 0) {
+				//Reset it to its remote group
+				needToResetToRemoteGroup = YES;
+			} else {
+				for (AIListGroup *group in self.groups)
+					[contact addContainingGroup:group];
+			}
 		}
 
 		[self containedObjectsOrOrderDidChange];
@@ -325,11 +337,16 @@
 		/* Now that we're done reconfigured ourselves and the recently removed object,
 		 * tell the contactController about the change in the removed object.
 		 */
-		if (noteRemoteGroupingChanged) {
+		if (needToResetToRemoteGroup) {
 			[(AIListContact *)inObject restoreGrouping];
 		}
 
 		[inObject release];
+		
+		return YES;
+	} else {
+		AILogWithSignature(@"%@: Asked to remove %@, but it's not actually contained therein", self, inObject);
+		return NO;
 	}
 }
 
@@ -808,7 +825,13 @@
 //FormattedUID will return nil if we have multiple different UIDs contained within us
 - (NSString *)formattedUID
 {
+#ifdef META_TYPE_DEBUG
+	return (containsOnlyOneUniqueContact ? 
+			[self.preferredContact.formattedUID stringByAppendingString:@" (uniqueMeta)"] : 
+			@"meta");	
+#else
 	return containsOnlyOneUniqueContact ? self.preferredContact.formattedUID : nil;
+#endif
 }
 
 - (NSString *)longDisplayName
diff -r fac84dd8c6f6 -r ff2202a84a35 Frameworks/Adium Framework/Source/ESDebugAILog.m
--- a/Frameworks/Adium Framework/Source/ESDebugAILog.m	Sun Sep 19 03:40:49 2010 +0200
+++ b/Frameworks/Adium Framework/Source/ESDebugAILog.m	Sun Sep 19 16:04:07 2010 -0500
@@ -58,6 +58,8 @@
 }
 
 void AILog_impl (NSString *format, ...) {
+	if (!AIDebugLoggingEnabled) return;
+
 	va_list		ap; /* Points to each unamed argument in turn */
 	NSString	*debugMessage;
 	
@@ -72,6 +74,8 @@
 }
 
 void AILogWithPrefix_impl (const char *prefix, NSString *format, ...) {
+	if (!AIDebugLoggingEnabled) return;
+
 	va_list		ap; /* Points to each unamed argument in turn */
 	NSString	*debugMessage, *actualMessage;
 	
diff -r fac84dd8c6f6 -r ff2202a84a35 Plugins/Purple Service/CBPurpleAccount.m
--- a/Plugins/Purple Service/CBPurpleAccount.m	Sun Sep 19 03:40:49 2010 +0200
+++ b/Plugins/Purple Service/CBPurpleAccount.m	Sun Sep 19 16:04:07 2010 -0500
@@ -538,7 +538,6 @@
 - (void)delayedUpdateContactStatus:(AIListContact *)inContact
 {
     //Request profile
-	AILogWithSignature(@"");
 	[purpleAdapter getInfoFor:inContact.UID onAccount:self];
 }
 
diff -r fac84dd8c6f6 -r ff2202a84a35 Plugins/Purple Service/adiumPurpleSignals.m
--- a/Plugins/Purple Service/adiumPurpleSignals.m	Sun Sep 19 03:40:49 2010 +0200
+++ b/Plugins/Purple Service/adiumPurpleSignals.m	Sun Sep 19 16:04:07 2010 -0500
@@ -193,11 +193,8 @@
 		 * Failing that, we will get an alias specified remotely (either by the server or by the buddy).
 		 */
 		const char *alias = purple_buddy_get_alias_only(buddy);
-		
-		AILogWithSignature(@"%@ -> %s", contactLookupFromBuddy(buddy), alias);
 
 		if (alias) {
-			AILogWithSignature(@"%@", listContact);
 			[account updateContact:listContact
 						   toAlias:[NSString stringWithUTF8String:alias]];
 		}
diff -r fac84dd8c6f6 -r ff2202a84a35 Source/AIAliasSupportPlugin.m
--- a/Source/AIAliasSupportPlugin.m	Sun Sep 19 03:40:49 2010 +0200
+++ b/Source/AIAliasSupportPlugin.m	Sun Sep 19 16:04:07 2010 -0500
@@ -178,8 +178,7 @@
 	NSString		*alias = [userInfo objectForKey:@"Alias"];
 	if (!alias) {
 		alias = [object preferenceForKey:@"Alias"
-								   group:PREF_GROUP_ALIASES 
-				  ];
+								   group:PREF_GROUP_ALIASES];
 	}
 	
 	[self _applyAlias:alias
diff -r fac84dd8c6f6 -r ff2202a84a35 Source/AIAutomaticStatus.h
--- a/Source/AIAutomaticStatus.h	Sun Sep 19 03:40:49 2010 +0200
+++ b/Source/AIAutomaticStatus.h	Sun Sep 19 16:04:07 2010 -0500
@@ -24,7 +24,7 @@
 @interface AIAutomaticStatus : AIPlugin {
 	NSNumber						*fastUserSwitchID;
 	NSNumber						*screenSaverID;
-	NSNumber						*idleID;
+	NSNumber						*idleStatusID;
 	
 	NSNumber						*oldStatusID;
 	
@@ -33,7 +33,7 @@
 	
 	BOOL							fastUserSwitchEnabled;
 	BOOL							screenSaverEnabled;
-	BOOL							idleEnabled;
+	BOOL							idleStatusEnabled;
 	BOOL							reportIdleEnabled;
 	
 	double							idleReportInterval;
diff -r fac84dd8c6f6 -r ff2202a84a35 Source/AIAutomaticStatus.m
--- a/Source/AIAutomaticStatus.m	Sun Sep 19 03:40:49 2010 +0200
+++ b/Source/AIAutomaticStatus.m	Sun Sep 19 16:04:07 2010 -0500
@@ -150,7 +150,7 @@
 	// Stored status IDs
 	[fastUserSwitchID release];
 	[screenSaverID release];
-	[idleID release];
+	[idleStatusID release];
 	
 	[oldStatusID release];
 	
@@ -177,9 +177,9 @@
 	idleReportInterval = [[prefDict objectForKey:KEY_STATUS_REPORT_IDLE_INTERVAL] doubleValue];
 	
 	// Idle status change
-	[idleID release];
-	idleID = [[prefDict objectForKey:KEY_STATUS_AUTO_AWAY_STATUS_STATE_ID] retain];
-	idleEnabled = [[prefDict objectForKey:KEY_STATUS_AUTO_AWAY] boolValue];
+	[idleStatusID release];
+	idleStatusID = [[prefDict objectForKey:KEY_STATUS_AUTO_AWAY_STATUS_STATE_ID] retain];
+	idleStatusEnabled = [[prefDict objectForKey:KEY_STATUS_AUTO_AWAY] boolValue];
 	idleStatusInterval = [[prefDict objectForKey:KEY_STATUS_AUTO_AWAY_INTERVAL] doubleValue];
 	
 	// Fast user switch
@@ -226,17 +226,22 @@
 		
 		// This is very spammy when we're already idle.
 		if (duration >= idleStatusInterval && !(automaticStatusBitMap & AIAwayIdle)) {
-			AILogWithSignature(@"Idle (start) detected.");
+			NSDate *idleSince = [[notification userInfo] objectForKey:@"IdleSince"];
 			
-			if (idleEnabled) automaticStatusBitMap |= AIAwayIdle;
-			
-			// Update our idle time
-			if (reportIdleEnabled) {
-				[adium.preferenceController setPreference:[[notification userInfo] objectForKey:@"IdleSince"]
-												   forKey:@"IdleSince"
-													group:GROUP_ACCOUNT_STATUS];
+			if (![[adium.preferenceController preferenceForKey:@"IdleSince" group:GROUP_ACCOUNT_STATUS] isEqualToDate:idleSince]) {
+				AILogWithSignature(@"Idle (start) detected.");
+
+				if (idleStatusEnabled) automaticStatusBitMap |= AIAwayIdle;
+				
+				// Update our idle time
+				if (reportIdleEnabled) {
+					[adium.preferenceController setPreference:[[notification userInfo] objectForKey:@"IdleSince"]
+													   forKey:@"IdleSince"
+														group:GROUP_ACCOUNT_STATUS];
+				}
 			}
 		}
+		
 	} if ([notificationName isEqualToString:AIScreenLockDidStartNotification]) {
 		AILogWithSignature(@"Screenlock (start) detected.");
 		
@@ -286,7 +291,7 @@
 			statusID = screenSaverID;
 			
 		else if (automaticStatusBitMap & AIAwayIdle)	
-			statusID = idleID;
+			statusID = idleStatusID;
 			
 		else
 			[self returnFromAutoAway];
diff -r fac84dd8c6f6 -r ff2202a84a35 Source/AIContactController.m
--- a/Source/AIContactController.m	Sun Sep 19 03:40:49 2010 +0200
+++ b/Source/AIContactController.m	Sun Sep 19 16:04:07 2010 -0500
@@ -69,13 +69,15 @@
 #define SERVICE_ID_KEY					@"ServiceID"
 #define UID_KEY							@"UID"
 
+//#define CONTACT_MOVEMENT_DEBUG
+
 @interface AIListObject ()
 @property (readwrite, nonatomic) CGFloat orderIndex;
 @end
 
 @interface AIMetaContact ()
-- (void)removeObject:(AIListObject *)inObject;
 - (BOOL)addObject:(AIListObject *)inObject;
+- (BOOL)removeObject:(AIListObject *)inObject;
 - (AIListContact *)preferredContactForContentType:(NSString *)inType;
 @end
 
@@ -286,16 +288,22 @@
 		if (existingObject) {
 			//If an object exists in this group with the same UID and serviceID, create a MetaContact
 			//for the two.
-			[self groupContacts:[NSArray arrayWithObjects:listContact,existingObject,nil]];
+			AIMetaContact *metaContact = [self groupContacts:[NSArray arrayWithObjects:listContact,existingObject,nil]];
+			
+			AILogWithSignature(@"%@ and %@ match; grouped into %@",
+							   listContact, existingObject, metaContact);
+			
 			performedGrouping = YES;
 			
 		} else {
 			AIMetaContact	*metaContact = [contactToMetaContactLookupDict objectForKey:listContact.internalObjectID];
 			
-			//If no object exists in this group which matches, we should check if there is already
-			//a MetaContact holding a matching ListContact, since we should include this contact in it
-			//If we found a metaContact to which we should add, do it.
+			/* If no object exists in this group which matches, we should check if there is already
+			 * a MetaContact holding a matching ListContact, since we should include this contact in it
+			 * If we found a metaContact to which we should add, do it.
+			 */
 			if (metaContact) {
+				AILogWithSignature(@"%@: Add %@", metaContact, listContact);
 				[self addContact:listContact toMetaContact:metaContact];
 				performedGrouping = YES;
 			}
@@ -317,22 +325,31 @@
 - (void)_moveContactLocally:(AIListContact *)listContact fromGroups:(NSSet *)oldGroups toGroups:(NSSet *)groups
 {
 	//Protect with a retain while we are removing and adding the contact to our arrays
-	[listContact retain];
-	
-	[contactPropertiesObserverManager delayListObjectNotifications];
-	
-	//Remove this object from any local groups we have it in currently
-	for (AIListGroup *group in oldGroups) {
-		[group removeObject:listContact];
-		[self _didChangeContainer:group object:listContact];
+	if (![oldGroups isEqualToSet:groups]) {
+		[listContact retain];
+		
+		[contactPropertiesObserverManager delayListObjectNotifications];
+		
+#ifdef CONTACT_MOVEMENT_DEBUG
+		AILogWithSignature(@"%@: %@ --> %@", 
+						   listContact,
+						   (oldGroups.count ? oldGroups : nil), 
+						   (groups.count ? (groups.count == 1 ? [groups anyObject] ? groups) : nil));
+#endif
+		
+		//Remove this object from any local groups we have it in currently
+		for (AIListGroup *group in oldGroups) {
+			[group removeObject:listContact];
+			[self _didChangeContainer:group object:listContact];
+		}
+		
+		for (AIListGroup *group in groups)
+			[self _addContactLocally:listContact toGroup:group];
+		
+		[contactPropertiesObserverManager endListObjectNotificationsDelay];
+		
+		[listContact release];
 	}
-	
-	for (AIListGroup *group in groups)
-		[self _addContactLocally:listContact toGroup:group];
-	
-	[contactPropertiesObserverManager endListObjectNotificationsDelay];
-	
-	[listContact release];
 }
 
 //Post a list grouping changed notification for the object and containing object
@@ -569,27 +586,57 @@
 	}
 	
 	if (inContact == metaContact) return;
-	
+
+	AILogWithSignature(@"%@ will add %@", metaContact, inContact);
+
 	//If listObject contains other contacts, perform addContact:toMetaContact: recursively
 	if ([inContact conformsToProtocol:@protocol(AIContainingObject)]) {
+		AILogWithSignature(@"Adding recursively (%@)", ((AIListObject<AIContainingObject> *)inContact).containedObjects);
 		for (AIListContact *someObject in ((AIListObject<AIContainingObject> *)inContact).containedObjects) {
 			[self addContact:someObject toMetaContact:metaContact];
 		}
 		
 	} else {
 		//Obtain any metaContact this listObject is currently within, so we can remove it later
-		AIMetaContact *oldMetaContact = [contactToMetaContactLookupDict objectForKey:[inContact internalObjectID]];
+		AIMetaContact *oldMetaContact;
 		
-		if ([self _performAddContact:inContact toMetaContact:metaContact] && metaContact != oldMetaContact) {
-			//If this listObject was not in this metaContact in any form before, store the change
-			//Remove the list object from any other metaContact it is in at present
-			if (oldMetaContact)
-				[self removeContact:inContact fromMetaContact:oldMetaContact];
-			
-			[self _storeListObject:inContact inMetaContact:metaContact];
+		/* First, look for a metaContact which is -properly- associated with inContact, already.
+		 * That is, a metaContact that has current ownership but which should be disassociated, in faovr of the new
+		 * metaContact.
+		 */
+		oldMetaContact = [contactToMetaContactLookupDict objectForKey:[inContact internalObjectID]];
+		
+		if (metaContact == oldMetaContact) {
+			/* According to contactToMetaContactLookupDict, inContact is within metaContact already.
+			 * However, a single UID/serviceID pair can have multiple AIListContacts (for multiple accounts).
+			 * If Account A and Account B both have a contact like inContact, and we are looking at Account B's
+			 * contact now, we'll have already made a reassignment.  This contact does still need to be removed from
+			 * its parent, however.
+			 */
+			if ((inContact.parentContact != inContact) &&
+				([inContact.parentContact isKindOfClass:[AIMetaContact class]])) {
+				oldMetaContact = (AIMetaContact *)(inContact.parentContact);
+			}
+		}
+		
+		if ([self _performAddContact:inContact toMetaContact:metaContact]) {
+			if (metaContact != oldMetaContact) {
+				AILogWithSignature(@"oldMetaContact for %@ is %@", inContact.internalObjectID, oldMetaContact);
 
-			//Do the update thing
-			[contactPropertiesObserverManager _updateAllAttributesOfObject:metaContact];
+				//If this listObject was not in this metaContact in any form before, store the change
+				//Remove the list object from any other metaContact it is in at present
+				if (oldMetaContact)
+					[self removeContact:inContact fromMetaContact:oldMetaContact];
+				
+				[self _storeListObject:inContact inMetaContact:metaContact];
+				
+				//Do the update thing
+				[contactPropertiesObserverManager _updateAllAttributesOfObject:metaContact];
+			} else {
+				AILogWithSignature(@"The old metacontact was the same as the new metacontact");
+			}
+		} else {
+			AILogWithSignature(@"Failed to add %@ to %@", inContact, metaContact);
 		}
 	}
 }
@@ -633,21 +680,35 @@
 		
 		[adium.contactAlertsController mergeAndMoveContactAlertsFromListObject:listObject
 																  intoListObject:metaContact];
+		
+		AILogWithSignature(@"Updated %@'s containedContactsArray: %@", metaContact, containedContactsArray);
 	}
 	
 	[allMetaContactsDict release];
 	[containedContactsArray release];
 }
 
-//Actually adds a list contact to a meta contact. No preferences are changed.
-//Attempts to add the list object, causing group reassignment and updates our contactToMetaContactLookupDict
-//for quick lookup of the MetaContact given a AIListContact uniqueObjectID if successful.
+/*!
+ * @brief Makes the associations between an AIListContact and an AIMetaContact within memory
+ *
+ * No preferences are changed; this is an internal step during the process of moving a contact into a metacontact.
+ *
+ * Attempts to add the list object, causing group reassignment and updates our contactToMetaContactLookupDict
+ * for quick lookup of the MetaContact given a AIListContact uniqueObjectID if successful.
+ *
+ * @result YES if a change was made; NO if inContact is already contained by metaContact
+ */
 - (BOOL)_performAddContact:(AIListContact *)inContact toMetaContact:(AIMetaContact *)metaContact
 {
+	if (inContact.metaContact == metaContact) {
+		AILogWithSignature(@"%@'s metaContact is already %@", inContact, metaContact);
+		return NO;
+	}
+
 	//we only allow group->meta->contact, not group->meta->meta->contact
 	NSParameterAssert([metaContact canContainObject:inContact]);
-
-	BOOL								success;
+	
+	BOOL success;
 	
 	//Remove the object from its previous containing groups
 	[self _moveContactLocally:inContact fromGroups:inContact.groups toGroups:[NSSet set]];
@@ -667,6 +728,8 @@
 
 - (void)removeContact:(AIListContact *)inContact fromMetaContact:(AIMetaContact *)metaContact
 {
+	AILogWithSignature(@"%@: Remove %@", metaContact, inContact);
+
 	//we only allow group->meta->contact, not group->meta->meta->contact
 	NSParameterAssert(![inContact conformsToProtocol:@protocol(AIContainingObject)]);
 	
@@ -709,13 +772,19 @@
 		[newContainedContactsArray release];
 		[newAllMetaContactsDict release];
 	}
-	
-	//The listObject can be within the metaContact without us finding a containedContactDict if we are removing multiple
-	//listContacts referring to the same UID & serviceID combination - that is, on multiple accounts on the same service.
-	//We therefore request removal of the object regardless of the if (containedContactDict) check above.
-	[metaContact removeObject:inContact];
-	
-	[self _didChangeContainer:metaContact object:inContact];
+
+	/* Remove all contacts matching this service/UID from the metacontact */
+	[contactPropertiesObserverManager delayListObjectNotifications];
+
+	for (AIListContact *matchingContact in [self allContactsWithService:inContact.service UID:inContact.UID]) {
+		if ([metaContact removeObject:matchingContact]) {
+			[contactPropertiesObserverManager _updateAllAttributesOfObject:inContact];
+			[self _didChangeContainer:metaContact object:inContact];
+		}		
+	}
+
+	[contactPropertiesObserverManager _updateAllAttributesOfObject:metaContact];
+	[contactPropertiesObserverManager endListObjectNotificationsDelay];
 }
 
 /*!
@@ -838,8 +907,10 @@
 
 	//Create a new metaContact is we didn't find one.
 	if (!metaContact) {
-		AILogWithSignature(@"New metacontact to group %@", contactsToGroupArray);
 		metaContact = [self metaContactWithObjectID:nil];
+		AILogWithSignature(@"Created new metacontact %@ for grouping %@", metaContact, contactsToGroupArray);
+	} else {
+		AILogWithSignature(@"Existing metacontact %@ will now gain %@", metaContact, contactsToGroupArray);
 	}
 	
 	/* Add all these contacts to our MetaContact.
@@ -849,6 +920,8 @@
 		[self addContact:listContact toMetaContact:metaContact];
 	}
 	
+	AILogWithSignature(@"Completed groupContacts; metaContact is %@", metaContact);
+
 	return metaContact;
 }
 
@@ -1453,15 +1526,18 @@
 
 - (void)moveContact:(AIListContact *)contact fromGroups:(NSSet *)oldGroups intoGroups:(NSSet *)groups
 {
+	AILogWithSignature(@"moveContact %@ [meta=%p; contained by %@; %@] from %@ into %@", 
+					   contact, 
+					   contact.metaContact, contact.containingObjects, (contact.existsServerside ? @"exists serverside" : @"does NOT exist serverside"),
+					   oldGroups,groups);
+
 	[contactPropertiesObserverManager delayListObjectNotifications];
 	if (contact.metaContact) {
 		AIMetaContact *meta = contact.metaContact;
 		//Remove from the contactToMetaContactLookupDict first so we don't try to reinsert into this metaContact
 		[contactToMetaContactLookupDict removeObjectForKey:contact.internalObjectID];
 		
-		for (AIListContact *matchingContact in [self allContactsWithService:contact.service UID:contact.UID]) {
-			[self removeContact:matchingContact fromMetaContact:meta];
-		}
+		[self removeContact:contact fromMetaContact:meta];
 	}
 	
 	if (contact.existsServerside) {
diff -r fac84dd8c6f6 -r ff2202a84a35 Source/AIInfoInspectorPane.m
--- a/Source/AIInfoInspectorPane.m	Sun Sep 19 03:40:49 2010 +0200
+++ b/Source/AIInfoInspectorPane.m	Sun Sep 19 16:04:07 2010 -0500
@@ -520,10 +520,19 @@
 	
 	
 	if ([inObject isKindOfClass:[AIListContact class]]) {
-		currentAlias = [[(AIListContact *)inObject parentContact] preferenceForKey:@"Alias"
-																			 group:PREF_GROUP_ALIASES];
-		AILogWithSignature(@"inObject is %@; parentContact is %@. Preference is %@.",
-						   inObject, [(AIListContact *)inObject parentContact], currentAlias);
+		AIListContact *parentContact = [(AIListContact *)inObject parentContact];
+	
+		currentAlias = [parentContact preferenceForKey:@"Alias"
+												 group:PREF_GROUP_ALIASES];
+		
+		if (inObject == parentContact) {
+			AILogWithSignature(@"%@: current alias %@.",
+							   inObject, currentAlias);
+			
+		} else {
+			AILogWithSignature(@"updating alias for %@; parent %@ --> current alias %@.",
+							   inObject, [(AIListContact *)inObject parentContact], currentAlias);
+		}
 	} else {
 		currentAlias = [inObject preferenceForKey:@"Alias"
 											group:PREF_GROUP_ALIASES];		
diff -r fac84dd8c6f6 -r ff2202a84a35 Source/AIListController.m
--- a/Source/AIListController.m	Sun Sep 19 03:40:49 2010 +0200
+++ b/Source/AIListController.m	Sun Sep 19 16:04:07 2010 -0500
@@ -700,9 +700,12 @@
 		
 		[[AIContactObserverManager sharedManager] delayListObjectNotifications];
 
+		AILogWithSignature(@"Dropping into %@ (%@)", item, item.listObject);
+
 		//Move the list object to its new location
 		if ([item.listObject isKindOfClass:[AIListGroup class]]) {
 			/* Can't drop into the offline group */
+
 			if (item.listObject != adium.contactController.offlineGroup) {
 				AIListGroup *group = (AIListGroup *)(item.listObject);
 				
@@ -737,6 +740,8 @@
 
 							// Contact being moved to a new group.
 							// Holding option copies into the new group (like in Finder)
+							
+							AILogWithSignature(@"Moving %@ from %@ to %@", listObject, sourceGroups, group);
 							[adium.contactController moveContact:(AIListContact *)listObject
 													  fromGroups:sourceGroups
 													  intoGroups:[NSSet setWithObject:group]];
@@ -751,6 +756,9 @@
 						}
 					}
 					
+					AILogWithSignature(@"%@: moveContainedObject %@ to %f", group, listObject, index);
+
+					
 					[group moveContainedObject:listObject toIndex:index];
 					[adium.contactController sortListObject:listObject];
 				}
diff -r fac84dd8c6f6 -r ff2202a84a35 Source/AIListWindowController.m
--- a/Source/AIListWindowController.m	Sun Sep 19 03:40:49 2010 +0200
+++ b/Source/AIListWindowController.m	Sun Sep 19 16:04:07 2010 -0500
@@ -288,7 +288,6 @@
 
 - (void)setWindowLevel:(NSInteger)level
 {
-	AILogWithSignature(@"Setting to %i", level);
 	[[self window] setLevel:level];
 }
 




More information about the commits mailing list