2 * Adium is the legal property of its developers, whose names are listed in the copyright file included
3 * with this source distribution.
5 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
6 * General Public License as published by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
10 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
11 * Public License for more details.
13 * You should have received a copy of the GNU General Public License along with this program; if not,
14 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 #import "AIPreferenceController.h"
18 #import "ESContactAlertsController.h"
19 #import <AIUtilities/AIMenuAdditions.h>
20 #import <AIUtilities/ESImageAdditions.h>
21 #import <Adium/AIListObject.h>
23 @interface ESContactAlertsController (PRIVATE)
24 - (NSMutableArray *)appendEventsForObject:(AIListObject *)listObject eventID:(NSString *)eventID toArray:(NSMutableArray *)events;
25 - (void)addMenuItemsForEventHandlers:(NSDictionary *)inEventHandlers toArray:(NSMutableArray *)menuItemArray withTarget:(id)target forGlobalMenu:(BOOL)global;
26 - (void)removeAllAlertsFromListObject:(AIListObject *)listObject;
29 @implementation ESContactAlertsController
31 int eventMenuItemSort(id menuItemA, id menuItemB, void *context);
32 int actionMenuItemSort(id menuItemA, id menuItemB, void *context);
34 static NSMutableDictionary *eventHandlersByGroup[EVENT_HANDLER_GROUP_COUNT];
35 static NSMutableDictionary *globalOnlyEventHandlersByGroup[EVENT_HANDLER_GROUP_COUNT];
42 static BOOL didInitialize = NO;
45 for(i = 0; i < EVENT_HANDLER_GROUP_COUNT; i++){
46 eventHandlersByGroup[i] = nil;
47 globalOnlyEventHandlersByGroup[i] = nil;
55 - (void)initController
57 globalOnlyEventHandlers = [[NSMutableDictionary alloc] init];
58 eventHandlers = [[NSMutableDictionary alloc] init];
59 actionHandlers = [[NSMutableDictionary alloc] init];
62 - (void)closeController
69 [globalOnlyEventHandlers release]; globalOnlyEventHandlers = nil;
70 [eventHandlers release]; eventHandlers = nil;
71 [actionHandlers release]; actionHandlers = nil;
77 //Events ---------------------------------------------------------------------------------------------------------------
79 //Register a potential event
80 - (void)registerEventID:(NSString *)eventID
81 withHandler:(id <AIEventHandler>)handler
82 inGroup:(AIEventHandlerGroupType)inGroup
83 globalOnly:(BOOL)global
86 [globalOnlyEventHandlers setObject:handler forKey:eventID];
88 if(!globalOnlyEventHandlersByGroup[inGroup]) globalOnlyEventHandlersByGroup[inGroup] = [[NSMutableDictionary alloc] init];
89 [globalOnlyEventHandlersByGroup[inGroup] setObject:handler forKey:eventID];
92 [eventHandlers setObject:handler forKey:eventID];
94 if(!eventHandlersByGroup[inGroup]) eventHandlersByGroup[inGroup] = [[NSMutableDictionary alloc] init];
95 [eventHandlersByGroup[inGroup] setObject:handler forKey:eventID];
99 //Return all event IDs for groups/contacts
100 - (NSArray *)allEventIDs
102 return([[eventHandlers allKeys] arrayByAddingObjectsFromArray:[globalOnlyEventHandlers allKeys]]);
105 - (NSString *)longDescriptionForEventID:(NSString *)eventID forListObject:(AIListObject *)listObject
107 id <AIEventHandler> handler;
109 handler = [eventHandlers objectForKey:eventID];
110 if(!handler) handler = [globalOnlyEventHandlers objectForKey:eventID];
112 return([handler longDescriptionForEventID:eventID forListObject:listObject]);
115 //Returns a menu of all events
116 //- Selector called on event selection is selectEvent:
117 //- A menu item's represented object is the dictionary describing the event it represents
118 - (NSMenu *)menuOfEventsWithTarget:(id)target forGlobalMenu:(BOOL)global
120 NSEnumerator *enumerator;
125 menu = [[NSMenu allocWithZone:[NSMenu zone]] init];
126 [menu setAutoenablesItems:NO];
128 enumerator = [[self arrayOfMenuItemsForEventsWithTarget:target forGlobalMenu:global] objectEnumerator];
129 while(item = [enumerator nextObject]){
133 return [menu autorelease];
136 - (NSArray *)arrayOfMenuItemsForEventsWithTarget:(id)target forGlobalMenu:(BOOL)global
138 NSMutableArray *menuItemArray = [NSMutableArray array];
139 BOOL addedItems = NO;
142 for(i = 0; i < EVENT_HANDLER_GROUP_COUNT; i++){
143 NSMutableArray *groupMenuItemArray;
145 //Create an array of menu items for this group
146 groupMenuItemArray = [NSMutableArray array];
148 [self addMenuItemsForEventHandlers:eventHandlersByGroup[i]
149 toArray:groupMenuItemArray
151 forGlobalMenu:global];
153 [self addMenuItemsForEventHandlers:globalOnlyEventHandlersByGroup[i]
154 toArray:groupMenuItemArray
156 forGlobalMenu:global];
159 if([groupMenuItemArray count]){
160 //Add a separator if we are adding a group and we have added before
162 [menuItemArray addObject:[NSMenuItem separatorItem]];
167 //Sort the array of menuItems alphabetically by title within this group
168 [groupMenuItemArray sortUsingFunction:eventMenuItemSort context:nil];
170 [menuItemArray addObjectsFromArray:groupMenuItemArray];
174 return(menuItemArray);
177 - (void)addMenuItemsForEventHandlers:(NSDictionary *)inEventHandlers toArray:(NSMutableArray *)menuItemArray withTarget:(id)target forGlobalMenu:(BOOL)global
179 NSEnumerator *enumerator;
181 NSMenuItem *menuItem;
183 enumerator = [inEventHandlers keyEnumerator];
184 while((eventID = [enumerator nextObject])){
185 id <AIEventHandler> eventHandler = [inEventHandlers objectForKey:eventID];
187 menuItem = [[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:(global ?
188 [eventHandler globalShortDescriptionForEventID:eventID] :
189 [eventHandler shortDescriptionForEventID:eventID])
191 action:@selector(selectEvent:)
193 [menuItem setRepresentedObject:eventID];
194 [menuItemArray addObject:menuItem];
199 int eventIDSort(id objectA, id objectB, void *context){
201 id <AIEventHandler> eventHandlerA;
202 id <AIEventHandler> eventHandlerB;
204 //Determine the group of each eventID
205 for(groupA = 0; groupA < EVENT_HANDLER_GROUP_COUNT; groupA++){
206 eventHandlerA = [eventHandlersByGroup[groupA] objectForKey:objectA];
208 eventHandlerA = [globalOnlyEventHandlersByGroup[groupA] objectForKey:objectA];
211 if(eventHandlerA) break;
214 //Determine the group of each eventID
215 for(groupB = 0; groupB < EVENT_HANDLER_GROUP_COUNT; groupB++){
216 eventHandlerB = [eventHandlersByGroup[groupB] objectForKey:objectB];
218 eventHandlerB = [globalOnlyEventHandlersByGroup[groupB] objectForKey:objectB];
221 if(eventHandlerB) break;
225 return NSOrderedAscending;
227 }else if(groupB < groupA){
228 return NSOrderedDescending;
231 NSString *descriptionA = [eventHandlerA globalShortDescriptionForEventID:objectA];
232 NSString *descriptionB = [eventHandlerA globalShortDescriptionForEventID:objectB];
234 return ([descriptionA caseInsensitiveCompare:descriptionB]);
238 - (NSArray *)sortedArrayOfEventIDsFromArray:(NSArray *)inArray
240 return([inArray sortedArrayUsingFunction:eventIDSort context:NULL]);
243 - (NSImage *)imageForEventID:(NSString *)eventID
245 id <AIEventHandler> eventHandler;
247 eventHandler = [eventHandlers objectForKey:eventID];
248 if(!eventHandler) eventHandler = [globalOnlyEventHandlers objectForKey:eventID];
250 return([eventHandler imageForEventID:eventID]);
254 Generate an event, returning a set of the actionIDs which were performed.
255 If perviouslyPerformedActionIDs is non-nil, it indicates a set of actionIDs which should be treated as if
256 they had already been performed in this invocation.
258 - (NSSet *)generateEvent:(NSString *)eventID forListObject:(AIListObject *)listObject userInfo:(id)userInfo previouslyPerformedActionIDs:(NSSet *)previouslyPerformedActionIDs
260 NSArray *alerts = [self appendEventsForObject:listObject eventID:eventID toArray:nil];
261 NSMutableSet *performedActionIDs = nil;
263 if(alerts && [alerts count]){
264 NSEnumerator *enumerator;
267 performedActionIDs = (previouslyPerformedActionIDs ?
268 [[previouslyPerformedActionIDs mutableCopy] autorelease]:
271 //We go from contact->group->root; a given action will only fire once for this event
272 enumerator = [alerts objectEnumerator];
274 //Process each alert (There may be more than one for an event)
275 while(alert = [enumerator nextObject]){
277 id <AIActionHandler> actionHandler;
279 actionID = [alert objectForKey:KEY_ACTION_ID];
280 actionHandler = [actionHandlers objectForKey:actionID];
282 if((![performedActionIDs containsObject:actionID]) || ([actionHandler allowMultipleActionsWithID:actionID])){
283 [actionHandler performActionID:actionID
284 forListObject:listObject
285 withDetails:[alert objectForKey:KEY_ACTION_DETAILS]
286 triggeringEventID:eventID
289 //If this alert was a single-fire alert, we can delete it now
290 if([[alert objectForKey:KEY_ONE_TIME_ALERT] intValue]){
291 [self removeAlert:alert fromListObject:listObject];
294 //We don't want to perform this action again for this event
295 [performedActionIDs addObject:actionID];
300 [[adium notificationCenter] postNotificationName:eventID
304 /* If we generated a new perfromedActionIDs, return it. If we didn't, return the original
305 * previouslyPerformedActionIDs, which may also be nil or may be actionIDs performed on some previous invocation.
307 return (performedActionIDs ? performedActionIDs : previouslyPerformedActionIDs);
311 Append events for the passed object to the specified array.
312 Create the array if passed nil.
313 Return an array which contains the object's own events followed by its containingObject's events.
314 If the object is nil, we retrieve the global preferences.
316 This method is intended to be called recursively; it should generate an array which has alerts from:
317 contact->metaContact->group->global preferences (skipping any which don't exist).
319 - (NSMutableArray *)appendEventsForObject:(AIListObject *)listObject eventID:(NSString *)eventID toArray:(NSMutableArray *)events
323 // AILog(@"appendEventsForObject: %@ eventID: %@ toArray: %@",preferenceSource,eventID,events);
325 //Add events for this object (replacing any inherited from the containing object so that this object takes precendence)
326 newEvents = [[[adium preferenceController] preferenceForKey:KEY_CONTACT_ALERTS
327 group:PREF_GROUP_CONTACT_ALERTS
328 objectIgnoringInheritance:listObject] objectForKey:eventID];
330 if(newEvents && [newEvents count]){
331 if(!events) events = [NSMutableArray array];
332 [events addObjectsFromArray:newEvents];
335 //Get all events from the contanining object if we have an object
337 //If listObject doesn't have a containingObject, this will pass nil
338 events = [self appendEventsForObject:[listObject containingObject]
346 - (NSString *)defaultEventID
348 NSString *defaultEventID = [[adium preferenceController] preferenceForKey:KEY_DEFAULT_EVENT_ID
349 group:PREF_GROUP_CONTACT_ALERTS];
350 if (![eventHandlers objectForKey:defaultEventID]){
351 defaultEventID = [[eventHandlers allKeys] objectAtIndex:0];
354 return defaultEventID;
357 - (NSString *)eventIDForEnglishDisplayName:(NSString *)displayName
359 NSEnumerator *enumerator;
362 enumerator = [eventHandlers keyEnumerator];
363 while((eventID = [enumerator nextObject])){
364 id <AIEventHandler> eventHandler = [eventHandlers objectForKey:eventID];
365 if ([[eventHandler englishGlobalShortDescriptionForEventID:eventID] isEqualToString:displayName]){
370 enumerator = [globalOnlyEventHandlers keyEnumerator];
371 while((eventID = [enumerator nextObject])){
372 id <AIEventHandler> eventHandler = [globalOnlyEventHandlers objectForKey:eventID];
373 if ([[eventHandler englishGlobalShortDescriptionForEventID:eventID] isEqualToString:displayName]){
381 - (NSString *)globalShortDescriptionForEventID:(NSString *)eventID
383 id <AIEventHandler> eventHandler;
385 eventHandler = [eventHandlers objectForKey:eventID];
386 if(!eventHandler) eventHandler = [globalOnlyEventHandlers objectForKey:eventID];
389 return [eventHandler globalShortDescriptionForEventID:eventID];
395 - (NSString *)naturalLanguageDescriptionForEventID:(NSString *)eventID
396 listObject:(AIListObject *)listObject
397 userInfo:(id)userInfo
398 includeSubject:(BOOL)includeSubject
400 id <AIEventHandler> eventHandler;
402 eventHandler = [eventHandlers objectForKey:eventID];
403 if(!eventHandler) eventHandler = [globalOnlyEventHandlers objectForKey:eventID];
406 return([eventHandler naturalLanguageDescriptionForEventID:eventID
407 listObject:listObject
409 includeSubject:includeSubject]);
415 int eventMenuItemSort(id menuItemA, id menuItemB, void *context){
416 return ([[menuItemA title] caseInsensitiveCompare:[menuItemB title]]);
420 //Actions --------------------------------------------------------------------------------------------------------------
422 - (void)registerActionID:(NSString *)actionID withHandler:(id <AIActionHandler>)handler
424 [actionHandlers setObject:handler forKey:actionID];
427 //Return all available actions
428 - (NSDictionary *)actionHandlers
430 return(actionHandlers);
433 //Returns a menu of all actions
434 //- Selector called on action selection is selectAction:
435 //- A menu item's represented object is the dictionary describing the action it represents
436 - (NSMenu *)menuOfActionsWithTarget:(id)target
438 NSEnumerator *enumerator;
440 NSMenuItem *menuItem;
442 NSMutableArray *menuItemArray;
445 menu = [[NSMenu alloc] init];
446 [menu setAutoenablesItems:NO];
448 menuItemArray = [[NSMutableArray alloc] init];
450 //Insert a menu item for each available action
451 enumerator = [actionHandlers keyEnumerator];
452 while((actionID = [enumerator nextObject])){
453 id <AIActionHandler> actionHandler = [actionHandlers objectForKey:actionID];
455 menuItem = [[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:[actionHandler shortDescriptionForActionID:actionID]
457 action:@selector(selectAction:)
459 [menuItem setRepresentedObject:actionID];
460 [menuItem setImage:[[actionHandler imageForActionID:actionID] imageByScalingToSize:NSMakeSize(16,16)]];
462 [menuItemArray addObject:menuItem];
466 //Sort the array of menuItems alphabetically by title
467 [menuItemArray sortUsingFunction:actionMenuItemSort context:nil];
469 enumerator = [menuItemArray objectEnumerator];
470 while(menuItem = [enumerator nextObject]){
471 [menu addItem:menuItem];
474 [menuItemArray release];
476 return [menu autorelease];
479 - (NSString *)defaultActionID
481 NSString *defaultActionID = [[adium preferenceController] preferenceForKey:KEY_DEFAULT_ACTION_ID
482 group:PREF_GROUP_CONTACT_ALERTS];
483 if (![actionHandlers objectForKey:defaultActionID]){
484 defaultActionID = [[actionHandlers allKeys] objectAtIndex:0];
487 return defaultActionID;
490 int actionMenuItemSort(id menuItemA, id menuItemB, void *context){
491 return ([[menuItemA title] caseInsensitiveCompare:[menuItemB title]]);
494 //Alerts ---------------------------------------------------------------------------------------------------------------
496 //Returns an array of all the alerts of a given list object
497 - (NSArray *)alertsForListObject:(AIListObject *)listObject
499 return([self alertsForListObject:listObject withEventID:nil actionID:nil]);
502 - (NSArray *)alertsForListObject:(AIListObject *)listObject withEventID:(NSString *)eventID actionID:(NSString *)actionID
504 NSDictionary *contactAlerts = [[adium preferenceController] preferenceForKey:KEY_CONTACT_ALERTS
505 group:PREF_GROUP_CONTACT_ALERTS
506 objectIgnoringInheritance:listObject];
507 NSMutableArray *alertArray = [NSMutableArray array];
510 /* If we have an eventID, just look at the alerts for this eventID */
511 NSEnumerator *alertEnumerator;
514 alertEnumerator = [[contactAlerts objectForKey:eventID] objectEnumerator];
516 while(alert = [alertEnumerator nextObject]){
517 //If we don't have a specific actionID, or this one is right, add it
518 if(!actionID || [actionID isEqualToString:[alert objectForKey:KEY_ACTION_ID]]){
519 [alertArray addObject:alert];
524 /* If we don't have an eventID, look at all alerts */
525 NSEnumerator *groupEnumerator;
528 //Flatten the alert dict into an array
529 groupEnumerator = [contactAlerts keyEnumerator];
530 while(anEventID = [groupEnumerator nextObject]){
531 NSEnumerator *alertEnumerator;
534 alertEnumerator = [[contactAlerts objectForKey:anEventID] objectEnumerator];
535 while(alert = [alertEnumerator nextObject]){
536 //If we don't have a specific actionID, or this one is right, add it
537 if(!actionID || [actionID isEqualToString:[alert objectForKey:KEY_ACTION_ID]]){
538 [alertArray addObject:alert];
547 //Add an alert (passed as a dictionary) to a list object
548 - (void)addAlert:(NSDictionary *)newAlert toListObject:(AIListObject *)listObject setAsNewDefaults:(BOOL)setAsNewDefaults
550 NSString *newAlertEventID = [newAlert objectForKey:KEY_EVENT_ID];
551 NSMutableDictionary *contactAlerts;
552 NSMutableArray *eventArray;
554 [[adium preferenceController] delayPreferenceChangedNotifications:YES];
556 //Get the alerts for this list object
557 contactAlerts = [[[adium preferenceController] preferenceForKey:KEY_CONTACT_ALERTS
558 group:PREF_GROUP_CONTACT_ALERTS
559 objectIgnoringInheritance:listObject] mutableCopy];
560 if(!contactAlerts) contactAlerts = [[NSMutableDictionary alloc] init];
562 //Get the event array for the new alert, making a copy so we can modify it
563 eventArray = [[contactAlerts objectForKey:newAlertEventID] mutableCopy];
564 if(!eventArray) eventArray = [[NSMutableArray alloc] init];
566 //Avoid putting the exact same alert into the array twice
567 if ([eventArray indexOfObject:newAlert] == NSNotFound){
569 [eventArray addObject:newAlert];
571 //Put the modified event array back into the contact alert dict, and save our changes
572 [contactAlerts setObject:eventArray forKey:newAlertEventID];
573 [[adium preferenceController] setPreference:contactAlerts
574 forKey:KEY_CONTACT_ALERTS
575 group:PREF_GROUP_CONTACT_ALERTS
579 //Update the default events if requested
580 if(setAsNewDefaults){
581 [[adium preferenceController] setPreference:newAlertEventID
582 forKey:KEY_DEFAULT_EVENT_ID
583 group:PREF_GROUP_CONTACT_ALERTS];
584 [[adium preferenceController] setPreference:[newAlert objectForKey:KEY_ACTION_ID]
585 forKey:KEY_DEFAULT_ACTION_ID
586 group:PREF_GROUP_CONTACT_ALERTS];
590 [contactAlerts release];
591 [eventArray release];
593 [[adium preferenceController] delayPreferenceChangedNotifications:NO];
596 - (void)addGlobalAlert:(NSDictionary *)newAlert
598 [self addAlert:newAlert toListObject:nil setAsNewDefaults:NO];
601 //Remove the alert (passed as a dictionary, must be an exact = match) form a list object
602 - (void)removeAlert:(NSDictionary *)victimAlert fromListObject:(AIListObject *)listObject
604 NSMutableDictionary *contactAlerts = [[[adium preferenceController] preferenceForKey:KEY_CONTACT_ALERTS
605 group:PREF_GROUP_CONTACT_ALERTS
606 objectIgnoringInheritance:listObject] mutableCopy];
607 NSString *victimEventID = [victimAlert objectForKey:KEY_EVENT_ID];
608 NSMutableArray *eventArray;
610 //Get the event array containing the victim alert, making a copy so we can modify it
611 eventArray = [[contactAlerts objectForKey:victimEventID] mutableCopy];
614 [eventArray removeObject:victimAlert];
616 //Put the modified event array back into the contact alert dict, and save our changes
617 if ([eventArray count]){
618 [contactAlerts setObject:eventArray forKey:victimEventID];
620 [contactAlerts removeObjectForKey:victimEventID];
623 [[adium preferenceController] setPreference:contactAlerts
624 forKey:KEY_CONTACT_ALERTS
625 group:PREF_GROUP_CONTACT_ALERTS
627 [eventArray release];
628 [contactAlerts release];
631 - (void)removeAllAlertsFromListObject:(AIListObject *)listObject
633 [listObject setPreference:nil
634 forKey:KEY_CONTACT_ALERTS
635 group:PREF_GROUP_CONTACT_ALERTS];
638 - (void)removeAllGlobalAlertsWithActionID:(NSString *)actionID
640 NSDictionary *contactAlerts = [[adium preferenceController] preferenceForKey:KEY_CONTACT_ALERTS
641 group:PREF_GROUP_CONTACT_ALERTS];
642 NSMutableDictionary *newContactAlerts = [contactAlerts mutableCopy];
643 NSEnumerator *enumerator = [contactAlerts keyEnumerator];
644 NSString *victimEventID;
645 NSEnumerator *alertArrayEnumerator;
647 NSDictionary *alertDict;
649 //The contact alerts preference is a dictionary keyed by event. Each event key yields an array of dictionaries;
650 //each of these dictionaries represents an alert. We want to remove all dictionaries which represent alerts with
651 //the passed actionID
652 while (victimEventID = [enumerator nextObject]){
653 NSMutableArray *newEventArray = nil;
655 eventArray = [contactAlerts objectForKey:victimEventID];
657 //Enumerate each alert for this event
658 alertArrayEnumerator = [eventArray objectEnumerator];
659 while (alertDict = [alertArrayEnumerator nextObject]){
661 //We found an alertDict which needs to be removed
662 if ([[alertDict objectForKey:KEY_ACTION_ID] isEqualToString:actionID]){
663 //If this is the first modification to the current eventArray, make a mutableCopy with which to work
664 if (!newEventArray) newEventArray = [eventArray mutableCopy];
665 [newEventArray removeObject:alertDict];
669 //newEventArray will only be non-nil if we made changes; now that we have enumerated this eventArray, save them
671 if ([newEventArray count]){
672 [newContactAlerts setObject:newEventArray forKey:victimEventID];
674 [newContactAlerts removeObjectForKey:victimEventID];
678 [newEventArray release];
682 [[adium preferenceController] setPreference:newContactAlerts
683 forKey:KEY_CONTACT_ALERTS
684 group:PREF_GROUP_CONTACT_ALERTS];
685 [newContactAlerts release];
689 * @brief Remove all current global alerts and replace them with the alerts in allGlobalAlerts
691 * Used for setting a preset of events
693 - (void)setAllGlobalAlerts:(NSArray *)allGlobalAlerts
695 NSMutableDictionary *contactAlerts = [[NSMutableDictionary alloc] init];;
696 NSDictionary *eventDict;
697 NSEnumerator *enumerator;
699 [[adium preferenceController] delayPreferenceChangedNotifications:YES];
701 enumerator = [allGlobalAlerts objectEnumerator];
702 while(eventDict = [enumerator nextObject]){
703 NSMutableArray *eventArray;
704 NSString *eventID = [eventDict objectForKey:KEY_EVENT_ID];
706 /* Get the event array for this alert. Since we are creating the entire dictionary, we can be sure we are working
707 * with an NSMutableArray.
709 eventArray = [contactAlerts objectForKey:eventID];
710 if(!eventArray) eventArray = [NSMutableArray array];
713 [eventArray addObject:eventDict];
715 //Put the modified event array back into the contact alert dict
716 [contactAlerts setObject:eventArray forKey:eventID];
719 [[adium preferenceController] setPreference:contactAlerts
720 forKey:KEY_CONTACT_ALERTS
721 group:PREF_GROUP_CONTACT_ALERTS
723 [contactAlerts release];
725 [[adium preferenceController] delayPreferenceChangedNotifications:NO];
729 - (void)mergeAndMoveContactAlertsFromListObject:(AIListObject *)oldObject intoListObject:(AIListObject *)newObject
731 NSArray *oldAlerts = [self alertsForListObject:oldObject];
732 NSEnumerator *enumerator = [oldAlerts objectEnumerator];
733 NSDictionary *alertDict;
735 [[adium preferenceController] delayPreferenceChangedNotifications:YES];
737 //Add each alert to the target (addAlert:toListObject:setAsNewDefaults: will ensure identical alerts aren't added more than once)
738 while (alertDict = [enumerator nextObject]){
739 [self addAlert:alertDict toListObject:newObject setAsNewDefaults:NO];
742 //Remove the alerts from the originating list object
743 [self removeAllAlertsFromListObject:oldObject];
745 [[adium preferenceController] delayPreferenceChangedNotifications:NO];
749 - (BOOL)isMessageEvent:(NSString *)eventID
751 return(([eventHandlersByGroup[AIMessageEventHandlerGroup] objectForKey:eventID] != nil) ||
752 ([globalOnlyEventHandlersByGroup[AIMessageEventHandlerGroup] objectForKey:eventID] != nil));