Prevent dragging groups into groups. Fixes #8706
[adiumx.git] / Source / AIListBookmark.m
blob65886a97fbf07ae0c07d2457438d0e1a7e2ed248
1 //
2 //  AIListBookmark.m
3 //  Adium
4 //
5 //  Created by Erik Beerepoot on 19/07/07.
6 //  Copyright 2007 Adium Team. All rights reserved.
7 //
9 #import "AIListBookmark.h"
10 #import <Adium/AIAccountControllerProtocol.h>
11 #import <Adium/AIInterfaceControllerProtocol.h>
12 #import <Adium/AIChatControllerProtocol.h>
13 #import <Adium/AIContactControllerProtocol.h>
14 #import <Adium/AIUserIcons.h>
15 #import <Adium/AIService.h>
16 #import <Adium/AIChat.h>
18 #warning Wrong file location
20 #define KEY_CONTAINING_OBJECT_ID        @"ContainingObjectInternalObjectID"
21 #define OBJECT_STATUS_CACHE                     @"Object Status Cache"
23 #define KEY_ACCOUNT_INTERNAL_ID         @"AccountInternalObjectID"
25 @interface AIListBookmark (PRIVATE)
26 - (void)restoreGrouping;
27 @end
29 @implementation AIListBookmark
30 - (void)_initListBookmark
32         [[self account] addObserver:self
33                                          forKeyPath:@"Online"
34                                                 options:NSKeyValueObservingOptionNew
35                                                 context:NULL];
36         [self observeValueForKeyPath:@"Online" ofObject:[self account] change:nil context:NULL];
39 -(id)initWithChat:(AIChat *)inChat
41         if ((self = [self initWithUID:[NSString stringWithFormat:@"Bookmark:%@",[inChat uniqueChatID]]
42                                                    account:[inChat account]
43                                                    service:[[inChat account] service]])) {
44                 chatCreationDictionary = [[inChat chatCreationDictionary] copy];
45                 name = [[inChat name] copy];
46                 [self _initListBookmark];
47                 AILog(@"Created AIListBookmark %@", self);
48         }
49         return self;
52 - (id)initWithCoder:(NSCoder *)decoder
54         //Be sure to use [AIObject sharedAdiumInstance] rather than the adium ivar since that isn't set until super's init is called.
55         AIAccount *myAccount = [[[AIObject sharedAdiumInstance] accountController] accountWithInternalObjectID:[decoder decodeObjectForKey:KEY_ACCOUNT_INTERNAL_ID]];
56         if (!myAccount) {
57                 [self release];
58                 return nil;
59         }
61         if ((self = [self initWithUID:[decoder decodeObjectForKey:@"UID"]
62                                                   account:myAccount
63                                                   service:[[[AIObject sharedAdiumInstance] accountController] firstServiceWithServiceID:[decoder decodeObjectForKey:@"ServiceID"]]])) {
64                 chatCreationDictionary = [[decoder decodeObjectForKey:@"chatCreationDictionary"] retain];
65                 name = [[decoder decodeObjectForKey:@"name"] retain];
66                 [self _initListBookmark];
67                 AILog(@"Created AIListBookmark from coder with dict %@",chatCreationDictionary);
68                 [self restoreGrouping];
69                 
70         }
71         
72         return self;
75 - (void)encodeWithCoder:(NSCoder *)encoder
77         [encoder encodeObject:[self UID] forKey:@"UID"];
78         [encoder encodeObject:[[self account] internalObjectID] forKey:KEY_ACCOUNT_INTERNAL_ID];
79         [encoder encodeObject:[[self service] serviceID] forKey:@"ServiceID"];
80         [encoder encodeObject:[self chatCreationDictionary] forKey:@"chatCreationDictionary"];
81         [encoder encodeObject:name forKey:@"name"];
84 - (void)dealloc
86         [[self account] removeObserver:self forKeyPath:@"Online"];
88         [super dealloc];
90 - (NSString *)formattedUID
92         //XXX should query chat for its name if we're in it
93         return name;
96 - (NSDictionary *)chatCreationDictionary
98         return chatCreationDictionary;
101 - (NSString *)name
103         return name;
106 //XXX how to handle passwords
107 -(NSString*)password
109         return password;
112 -(void)setPassword:(NSString*)newPassword
114         if(password != newPassword) {
115                 [password release];
116                 password = [newPassword retain];
117         }
120 //When called, cache the internalObjectID of the new group so we can restore it immediately next time.
121 - (void)setContainingObject:(AIListObject <AIContainingObject> *)inGroup
123         NSString        *inGroupInternalObjectID = [inGroup internalObjectID];
125         //Save the change of containing object so it can be restored on launch next time if we are using groups.
126         //We don't save if we are not using groups as this set will be for the contact list root and probably not desired permanently.
127         if ([[adium contactController] useContactListGroups] &&
128                 inGroupInternalObjectID &&
129                 ![inGroupInternalObjectID isEqualToString:[self preferenceForKey:KEY_CONTAINING_OBJECT_ID
130                                                                                                                                    group:OBJECT_STATUS_CACHE
131                                                                                                    ignoreInheritedValues:YES]] &&
132                 (inGroup != [[adium contactController] offlineGroup])) {
133                 [self setPreference:inGroupInternalObjectID
134                                          forKey:KEY_CONTAINING_OBJECT_ID
135                                           group:OBJECT_STATUS_CACHE];
136         }
137         
138         [super setContainingObject:inGroup];
142  * @brief Restore the AIListGroup grouping into which this object was last manually placed
143  */
144 - (void)restoreGrouping
146         AIListGroup             *targetGroup = nil;
148         if ([[adium contactController] useContactListGroups]) {
149                 NSString                *oldContainingObjectID;
150                 AIListObject    *oldContainingObject;
152                 oldContainingObjectID = [self preferenceForKey:KEY_CONTAINING_OBJECT_ID
153                                                                                                  group:OBJECT_STATUS_CACHE];
154                 //Get the group's UID out of the internal object ID by taking the substring after "Group."
155                 oldContainingObject = ((oldContainingObjectID  && [oldContainingObjectID hasPrefix:@"Group."]) ?
156                                                            [[adium contactController] groupWithUID:[oldContainingObjectID substringFromIndex:6]] :
157                                                            nil);
159                 if (oldContainingObject &&
160                         [oldContainingObject isKindOfClass:[AIListGroup class]] &&
161                         oldContainingObject != [[adium contactController] contactList]) {
162                         //A previous grouping (to a non-root group) is saved; restore it
163                         targetGroup = (AIListGroup *)oldContainingObject;
164                 }
165         }
167         [[adium contactController] _moveContactLocally:self
168                                                                                    toGroup:(targetGroup ? targetGroup : [[adium contactController] contactList])];
171 - (void)openChat
173         AIChat *chat = [[adium chatController] existingChatWithName:[self name]
174                                                                                                           onAccount:[self account]];
175         if (chat && [[chat chatCreationDictionary] isEqualToDictionary:
176                                  [self chatCreationDictionary]]) {
177                 //An existing open chat matches this bookmark. Switch to it!
178                 [[adium interfaceController] setActiveChat:chat];
179                 
180         } else {
181                 //Open a new group chat (bookmarked chat)
182                 [[adium chatController] chatWithName:[self name]
183                                                                   identifier:NULL 
184                                                                    onAccount:[self account] 
185                                                         chatCreationInfo:[self chatCreationDictionary]];
186         }       
190  * @brief Can this object be part of a metacontact?
192  * It makes no sense for a bookmark to be in a metacontact, I think.
193  */
194 - (BOOL)canJoinMetaContacts
196         return NO;
199 #pragma mark -
200 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
202         if ([keyPath isEqualToString:@"Online"] && (object == [self account])) {
203                 BOOL online = [[self account] online];
204                 [self setVisible:online];
205                 [self setOnline:online notify:NotifyNow silently:YES];
206         }
209 #pragma mark -
210 - (NSString *)description
212         return [NSString stringWithFormat:@"<%@:%x %@ - %@ on %@>",NSStringFromClass([self class]), self, [self formattedUID], [self chatCreationDictionary], [self account]];
215 @end