⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 groupmanager.mm

📁 lumaqq
💻 MM
📖 第 1 页 / 共 2 页
字号:
/*
 * LumaQQ - Cross platform QQ client, special edition for Mac
 *
 * Copyright (C) 2007 luma <stubma@163.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#import "GroupManager.h"
#import "PreferenceConstants.h"
#import "PreferenceManager.h"
#import "FriendGroup.h"
#import "UserProperty.h"
#import "Signature.h"
#import "SubCluster.h"
#import "QQConstants.h"
#import "Member.h"
#import "PreferenceCache.h"
#import "LocalizedStringTool.h"
#import "FileTool.h"
#import "Constants.h"

#define _kKeyFriendlyGroups @"FriendlyGroup"
#define _kKeyStrangerGroup @"StrangerGroup"
#define _kKeyBlacklistGroup @"BlacklistGroup"
#define _kKeyClusterGroup @"ClusterGroup"
#define _kKeyMobileGroup @"MobileGroup"
#define _kKeyRecentContacts @"RecentContacts"
#define _kKeyDialogs @"Dialogs"

@implementation GroupManager

- (id) init {
	NSException* e = [NSException exceptionWithName:@"InitializationException"
											 reason:@"Don't use init of GroupManager"
										   userInfo:nil];
	[e raise];
	return nil;
}

- (id)initWithQQ:(UInt32)QQ domain:(MainWindowController*)domain {
	self = [super init];
	if (self != nil) {
		m_domain = [domain retain];
		m_QQ = QQ;
		m_dirty = NO;
		m_changed = NO;
		m_userRegistry = [[NSMutableDictionary dictionary] retain];
		m_clusterRegistry = [[NSMutableDictionary dictionary] retain];
		m_tempClusterRegistry = [[NSMutableDictionary dictionary] retain];
		m_mobileRegistry = [[NSMutableDictionary dictionary] retain];
		m_dialogsDummy = [[Dummy alloc] initWithType:kDummyDialogs name:L(@"LQDialogs")];
		m_recentContacts = [[NSMutableArray array] retain];
		
		// create me
		m_me = [[User alloc] initWithQQ:QQ domain:m_domain];
		[m_userRegistry setObject:m_me forKey:[NSNumber numberWithUnsignedInt:QQ]];
	}
	return self;
}

- (void) dealloc {
	[m_domain release];
	[m_groups release];
	[m_strangerGroup release];
	[m_blacklistGroup release];
	[m_clusterGroup release];
	[m_mobileGroup release];
	[m_userRegistry release];
	[m_clusterRegistry release];
	[m_mobileRegistry release];
	[m_tempClusterRegistry release];
	[m_dialogsDummy release];
	[m_dialogs release];
	[m_recentContacts release];
	[m_me release];
	[super dealloc];
}

#pragma mark -
#pragma mark load/save/initialize

- (void)loadGroups {
	// get path
	NSString* sFilePath = [FileTool getFilePath:m_QQ ForFile:kLQFileGroups];
	
	NSData* data = [NSData dataWithContentsOfFile:sFilePath];
	if(data) {
		NSKeyedUnarchiver* unar = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
		m_groups = [[unar decodeObjectForKey:_kKeyFriendlyGroups] retain];
		m_strangerGroup = [[unar decodeObjectForKey:_kKeyStrangerGroup] retain];
		m_blacklistGroup = [[unar decodeObjectForKey:_kKeyBlacklistGroup] retain];
		m_clusterGroup = [[unar decodeObjectForKey:_kKeyClusterGroup] retain];
		m_mobileGroup = [[unar decodeObjectForKey:_kKeyMobileGroup] retain];
		m_recentContacts = [[unar decodeObjectForKey:_kKeyRecentContacts] retain];
		m_dialogs = [[unar decodeObjectForKey:_kKeyDialogs] retain];
		[unar finishDecoding];
		[unar release];
		
		// check error
		if(m_groups == nil ||
		   m_strangerGroup == nil ||
		   m_blacklistGroup == nil ||
		   m_clusterGroup == nil ||
		   m_recentContacts == nil ||
		   m_mobileGroup == nil ||
		   m_dialogs == nil) {
			// release all and renew
			[m_groups release];
			[m_strangerGroup release];
			[m_blacklistGroup release];
			[m_clusterGroup release];
			[m_mobileGroup release];
			[m_recentContacts release];
			[m_dialogs release];
			m_groups = nil;
			m_strangerGroup = nil;
			m_blacklistGroup = nil;
			m_clusterGroup = nil;
			m_mobileGroup = nil;
			m_recentContacts = nil;
			m_dialogs = nil;
			[self initializeGroups:[NSArray array]];
		} else {
			// hash users and clusters
			NSEnumerator* groupEnum = [m_groups objectEnumerator];
			while(Group* g = [groupEnum nextObject]) {
				[self registerGroup:g];
			}
			[self registerGroup:m_strangerGroup];
			[self registerGroup:m_blacklistGroup];
			[self registerGroup:m_clusterGroup];
			[self registerGroup:m_mobileGroup];
			
			NSEnumerator* e = [m_recentContacts objectEnumerator];
			while(id obj = [e nextObject]) {
				if([obj isMemberOfClass:[User class]]) {
					User* u = (User*)obj;
					[u setDomain:m_domain];
					[m_userRegistry setObject:u forKey:[NSNumber numberWithUnsignedInt:[u QQ]]];
				} else if([obj isMemberOfClass:[Cluster class]]) {
					Cluster* c = (Cluster*)obj;
					[c setDomain:m_domain];
					if([c permanent])
						[m_clusterRegistry setObject:c forKey:[NSNumber numberWithUnsignedInt:[c internalId]]];
					else
						[m_tempClusterRegistry setObject:c forKey:[NSNumber numberWithUnsignedInt:[c internalId]]];
				} else if([obj isMemberOfClass:[Mobile class]]) {
					Mobile* m = (Mobile*)obj;
					[m setDomain:m_domain];
					[m_mobileRegistry setObject:m forKey:[m mobile]];
				}
			}
			
			e = [m_dialogs objectEnumerator];
			while(Cluster* dialog = [e nextObject]) {
				[dialog setDomain:m_domain];
				[m_tempClusterRegistry setObject:dialog forKey:[NSNumber numberWithUnsignedInt:[dialog internalId]]];
			}
		}
	} else
		[self initializeGroups:[NSArray array]];
}

- (void)saveGroups {
	if(!m_dirty)
		return;	
	m_dirty = NO;
	
	// get path
	NSString* sFilePath = [FileTool getFilePath:m_QQ ForFile:kLQFileGroups];
	
	// save to file
	NSMutableData* data = [NSMutableData data];
	NSKeyedArchiver* ar = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
	[ar setOutputFormat:NSPropertyListXMLFormat_v1_0];
	[ar encodeObject:m_groups forKey:_kKeyFriendlyGroups];
	[ar encodeObject:m_strangerGroup forKey:_kKeyStrangerGroup];
	[ar encodeObject:m_blacklistGroup forKey:_kKeyBlacklistGroup];
	[ar encodeObject:m_clusterGroup forKey:_kKeyClusterGroup];
	[ar encodeObject:m_mobileGroup forKey:_kKeyMobileGroup];
	[ar encodeObject:m_recentContacts forKey:_kKeyRecentContacts];
	[ar encodeObject:m_dialogs forKey:_kKeyDialogs];
	[ar finishEncoding];
	[data writeToFile:sFilePath atomically:YES];
}

- (void)registerGroup:(Group*)g {
	NSEnumerator* e = nil;
	if([g isUser]) {
		e = [g userEnumerator];
		while(User* u = [e nextObject]) {
			[u setDomain:m_domain];
			[m_userRegistry setObject:u forKey:[NSNumber numberWithUnsignedInt:[u QQ]]];
		}						
	} else if([g isCluster]) {
		e = [g clusterEnumerator];
		while(Cluster* c = [e nextObject]) {
			[c setDomain:m_domain];
			[m_clusterRegistry setObject:c forKey:[NSNumber numberWithUnsignedInt:[c internalId]]];
			
			NSEnumerator* scEnum = [c subClusterEnumerator];
			while(Cluster* sc = [scEnum nextObject]) {
				[sc setDomain:m_domain];
				[m_tempClusterRegistry setObject:sc forKey:[NSNumber numberWithUnsignedInt:[sc internalId]]];
			}
		}
	} else {
		e = [g mobileEnumerator];
		while(Mobile* m = [e nextObject]) {
			[m setDomain:m_domain];
			[m_mobileRegistry setObject:m forKey:[m mobile]];
		}	
	}
}

// 
// initialize groups, this will clear all groups and reconstruct them again
// not including "stranger" and "blacklist"
//
- (void)initializeGroups:(NSArray*)groupNames {
	// create
	if(m_groups == nil)
		m_groups = [[NSMutableArray array] retain];
	if(m_strangerGroup == nil)
		m_strangerGroup = [[Group alloc] initWithFlag:kGroupUser name:L(@"LQGroupStranger")];
	if(m_blacklistGroup == nil)
		m_blacklistGroup = [[Group alloc] initWithFlag:(kGroupUser | kGroupBlacklist) name:L(@"LQGroupBlacklist")];
	if(m_clusterGroup == nil)
		m_clusterGroup = [[Group alloc] initWithFlag:kGroupCluster];
	if(m_mobileGroup == nil)
		m_mobileGroup = [[Group alloc] initWithFlag:kGroupMobile];
	if(m_recentContacts == nil)
		m_recentContacts = [[NSMutableArray array] retain];	
	if(m_dialogs == nil)
		m_dialogs = [[NSMutableArray array] retain];
	
	// clean
	[m_groups removeAllObjects];
	
	// reset user group index
	NSEnumerator* e = [[m_userRegistry allValues] objectEnumerator];
	while(User* u = [e nextObject]) {
		[u setGroupIndex:kGroupIndexUndefined];
	}
	
	// add me
	[m_userRegistry setObject:m_me forKey:[NSNumber numberWithUnsignedInt:m_QQ]];
	
	// add my friends group
	if([m_groups count] == 0) {
		Group* g = [[Group alloc] initWithFlag:(kGroupUser | kGroupFriendly) name:L(@"LQGroupMyFriends")];
		[m_groups addObject:g];
		[g release];
	}
	
	// add normal friendly group
	int count = [m_groups count];
	int nameCount = [groupNames count];
	for(int i = 0; i < nameCount; i++) {
		// get group object or create a new one
		Group* g = nil;
		if(i + 1 < count)
			g = [self group:(i + 1)];
		else {
			g = [[Group alloc] init];
			[m_groups addObject:g];
			[g release];
		}		
		
		// set group name
		[g setName:[groupNames objectAtIndex:i]];
	}
}

#pragma mark -
#pragma mark getter and setter

- (UInt32)QQ {
	return m_QQ;
}

- (NSArray*)recentContacts {
	return m_recentContacts;
}

- (Group*)group:(int)index {
	if(index < 0)
		return nil;
	
	// if index exceed user friendly group, return others
	int count = [m_groups count];
	if(index >= count) {
		switch(index - count) {
			case 0:
				return m_strangerGroup;
			case 1:
				return m_blacklistGroup;
			case 2:
				return m_clusterGroup;
			case 3:
				return m_mobileGroup;
			default:
				return nil;
		}
	} else
		return [m_groups objectAtIndex:index];
}

- (Group*)clusterGroup {
	return m_clusterGroup;
}

- (Group*)strangerGroup {
	return m_strangerGroup;
}

- (Group*)blacklistGroup {
	return m_blacklistGroup;
}

- (Group*)mobileGroup {
	return m_mobileGroup;
}

#pragma mark -
#pragma mark sort

- (void)sortAll {
	NSEnumerator* e = [m_groups objectEnumerator];
	Group* g = nil;
	while(g = [e nextObject])
		[g sort];
}

#pragma mark -
#pragma mark user type check

- (BOOL)isUserFriendly:(User*)user {
	Group* g = [self group:[user groupIndex]];
	return g != nil && [g isUser] && [g isFriendly];
}

- (BOOL)isUserStranger:(User*)user {
	Group* g = [self group:[user groupIndex]];
	return g == nil || [g isUser] && [g isStranger];
}

- (BOOL)isUserBlacklist:(User*)user {
	Group* g = [self group:[user groupIndex]];
	return g != nil && [g isBlacklist];
}

#pragma mark -
#pragma mark edit methods

- (void)removeRecentContactAtIndex:(int)index {
	if(index < 0 || index >= [m_recentContacts count])
		return;
	
	[m_recentContacts removeObjectAtIndex:index];
	m_dirty = YES;
}

- (void)removeAllRecentContacts {
	[m_recentContacts removeAllObjects];
	m_dirty = YES;
}

- (void)addRecentContact:(id)object {
	// try remove it
	[m_recentContacts removeObject:object];
	
	// remove last contact
	PreferenceCache* cache = [PreferenceCache cache:m_QQ];
	while([m_recentContacts count] >= [cache maxRecentContact])
		[m_recentContacts removeLastObject];
	
	// add to first
	[m_recentContacts insertObject:object atIndex:0];
	
	// add to registry
	if([object isMemberOfClass:[User class]]) {
		id key = [NSNumber numberWithUnsignedInt:[(User*)object QQ]];
		if(![m_userRegistry objectForKey:key])
			[m_userRegistry setObject:object forKey:key];
	} else if([object isMemberOfClass:[Cluster class]]) {
		id key = [NSNumber numberWithUnsignedInt:[(Cluster*)object internalId]];
		if(![m_clusterRegistry objectForKey:key])
			[m_clusterRegistry setObject:object forKey:key];
	}
	
	// dirty flag
	m_dirty = YES;
}

- (void)addFriendGroups:(NSArray*)friendGroups {
	NSEnumerator* e = [friendGroups objectEnumerator];
	FriendGroup* fg = nil;
	while(fg = [e nextObject]) {		
		// get group object
		Group* g = [fg isUser] ? [self group:[fg groupIndex]] : [self clusterGroup];
		
		// create user or cluster
		if([g isUser]) {
			if([fg QQ] == m_QQ) {
				[g addUser:[self user:m_QQ]];
				[[self user:m_QQ] setGroupIndex:[fg groupIndex]];
			} else {
				User* u = [m_userRegistry objectForKey:[NSNumber numberWithUnsignedInt:[fg QQ]]];
				if(u == nil)
					u = [[[User alloc] initWithQQ:[fg QQ] domain:m_domain] autorelease];
				if([g addUser:u]) {
					// set group index
					[u setGroupIndex:[fg groupIndex]];
					
					// add to registry
					[m_userRegistry setObject:u forKey:[NSNumber numberWithUnsignedInt:[u QQ]]];
				}
			}
		} else {
			Cluster* c = [m_clusterRegistry objectForKey:[NSNumber numberWithUnsignedInt:[fg QQ]]];
			if(c == nil)
				c = [[[Cluster alloc] initWithInternalId:[fg QQ] domain:m_domain] autorelease];
			if([g addCluster:c]) {
				// add to registry
				[m_clusterRegistry setObject:c forKey:[NSNumber numberWithUnsignedInt:[c internalId]]];
			}			
		}		
		
		// set dirty flag
		m_dirty = YES;
	}
}

- (void)addFriends:(NSArray*)friends {
	NSEnumerator* e = [friends objectEnumerator];
	Friend* f = nil;
	while(f = [e nextObject]) {
		User* u = [self user:[f QQ]];
		if(u) {
			[u copyWithFriend:f];
			m_dirty = YES;
		}			
	}
}

- (void)setUserProperty:(NSArray*)properties {
	NSEnumerator* e = [properties objectEnumerator];
	UserProperty* prop = nil;
	while(prop = [e nextObject]) {
		User* u = [self user:[prop QQ]];
		if(u) {
			[u copyWithUserProperty:prop];
		}			
	}
}

- (void)setFriendLevel:(NSArray*)levels {
	NSEnumerator* e = [levels objectEnumerator];
	FriendLevel* level = nil;
	while(level = [e nextObject]) {
		User* u = [self user:[level QQ]];
		if(u) {
			[u copyWithFriendLevel:level];
		}			
	}
}

- (void)setSignature:(NSArray*)signatures {
	NSEnumerator* e = [signatures objectEnumerator];
	Signature* sig = nil;
	while(sig = [e nextObject]) {
		User* u = [self user:[sig QQ]];
		if(u) {
			[u copyWithSignature:sig];
		}			
	}
}

- (void)setRemarks:(NSArray*)remarks {
	NSEnumerator* e = [remarks objectEnumerator];
	FriendRemark* remark = nil;
	while(remark = [e nextObject]) {
		User* u = [self user:[remark QQ]];
		if(u) {
			[u copyWithRemarks:remark];
			m_dirty = YES;
		}
	}
}

- (void)setClusterInfo:(ClusterInfo*)info {
	Cluster* c = [self cluster:[info internalId]];
	
	if(c) {
		[c setClusterInfo:info];

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -