Automatically disable the Delete button in the Xtras Manager if no item is selected...
[adiumx.git] / Source / RAFBlockEditorWindowController.m
blob60de6bf3e0885ed984041d757e396f61379160f7
1 //
2 //  RAFBlockEditorWindow.m
3 //  Adium
4 //
5 //  Created by Augie Fackler on 5/26/05.
6 //  Copyright 2006 The Adium Team. All rights reserved.
7 //
9 #import "RAFBlockEditorWindowController.h"
10 #import "AIAccountController.h"
11 #import "AIContactController.h"
12 #import <AIUtilities/AICompletingTextField.h>
13 #import <AIUtilities/AIPopUpButtonAdditions.h>
14 #import <AIUtilities/AIMenuAdditions.h>
15 #import <Adium/AIAccount.h>
16 #import <Adium/AIAccountMenu.h>
17 #import <Adium/AIListContact.h>
18 #import <Adium/AIMetaContact.h>
19 #import <Adium/AIService.h>
21 #define BLOCK_EDITOR_TITLE AILocalizedString(@"Privacy Settings","Privacy Settings window title")
22 #define BLOCK_DONE      AILocalizedString(@"Done","Done button for Privacy Settings")
23 #define BLOCK_BLOCK     AILocalizedString(@"Add","Add button for Privacy Settings")
24 #define BLOCK_CANCEL    AILocalizedString(@"Cancel","Cancel button for Privacy Settings")
25 #define BLOCK_ACCOUNT AILocalizedString(@"Account:",nil)
26 #define BLOCK_BUDDY_COL AILocalizedString(@"Contact","Title of column containing user IDs of blocked contacts")
27 #define BLOCK_ACCOUNT_COL AILocalizedString(@"Account","Title of column containing blocking accounts")
29 @interface RAFBlockEditorWindowController (PRIVATE)
30 - (NSMenu *)privacyOptionsMenu;
31 - (AIAccount<AIAccount_Privacy> *)selectedAccount;
32 - (void)configureTextField;
33 - (NSSet *)contactsFromTextField;
34 - (AIPrivacyOption)selectedPrivacyOption;
35 @end
37 @implementation RAFBlockEditorWindowController
39 static RAFBlockEditorWindowController *sharedInstance = nil;
41 + (void)showWindow
42 {       
43         if (!sharedInstance) {
44                 sharedInstance = [[self alloc] initWithWindowNibName:@"BlockEditorWindow"];
45         }
47         [sharedInstance showWindow:nil];
48         [[sharedInstance window] makeKeyAndOrderFront:nil];
51 - (void)windowDidLoad
53         [[self window] setTitle:BLOCK_EDITOR_TITLE];
54         [cancelButton setLocalizedString:BLOCK_CANCEL];
55         [blockButton setLocalizedString:BLOCK_BLOCK];
56         [accountText setLocalizedString:BLOCK_ACCOUNT];
57         [[buddyCol headerCell] setTitle:BLOCK_BUDDY_COL];
58         [[accountCol headerCell] setTitle:BLOCK_ACCOUNT_COL];
60         [label_account setLocalizedString:BLOCK_ACCOUNT];
61         [label_privacyLevel setLocalizedString:AILocalizedString(@"Privacy level:", nil)];
62                 
63         accountColumnsVisible = YES;
64         [accountCol retain];
66         listContents = [[NSMutableArray alloc] init];
68         [stateChooser setMenu:[self privacyOptionsMenu]];
70         [[table tableColumnWithIdentifier:@"icon"] setDataCell:[[[NSImageCell alloc] init] autorelease]];
71         
72         accountMenu = [[AIAccountMenu accountMenuWithDelegate:self
73                                                                                           submenuType:AIAccountNoSubmenu
74                                                                                    showTitleVerbs:NO] retain];
75         [table registerForDraggedTypes:[NSArray arrayWithObjects:@"AIListObject", @"AIListObjectUniqueIDs",nil]];
77         [[adium notificationCenter] addObserver:self
78                                                                    selector:@selector(privacySettingsChangedExternally:)
79                                                                            name:@"AIPrivacySettingsChangedOutsideOfPrivacyWindow"
80                                                                          object:nil];
81         
82         [super windowDidLoad];
85 - (void)windowWillClose:(id)sender
87         [super windowWillClose:sender];
89         [[adium notificationCenter] removeObserver:self];
90         [sharedInstance release]; sharedInstance = nil;
93 - (NSString *)adiumFrameAutosaveName
95         return @"PrivacyWindow";
98 - (void)dealloc
100         [accountCol release];
101         [accountMenu release];
102         [listContents release];
103         [listContentsAllAccounts release];
104         
105         [super dealloc];
108 - (NSMutableArray*)listContents
110         return listContents;
113 - (void)setListContents:(NSArray*)newList
115         if (newList != listContents) {
116                 [listContents release];
117                 listContents = [newList mutableCopy];
118         }
121 #pragma mark Adding a contact to the list
122 - (IBAction)runBlockSheet:(id)sender
124         [field setStringValue:@""];
126         sheetAccountMenu = [[AIAccountMenu accountMenuWithDelegate:self
127                                                                                                    submenuType:AIAccountNoSubmenu
128                                                                                                 showTitleVerbs:NO] retain];
130         [NSApp beginSheet:sheet 
131            modalForWindow:[self window]
132                 modalDelegate:self 
133            didEndSelector:@selector(didEndSheet:returnCode:contextInfo:)
134                   contextInfo:nil];
137 - (void)selectAccountInSheet:(AIAccount *)inAccount
139         [popUp_sheetAccounts selectItemWithRepresentedObject:inAccount];
140         [self configureTextField];
141         
142         NSString        *userNameLabel = [[inAccount service] userNameLabel];
143         
144         [buddyText setStringValue:[(userNameLabel ? userNameLabel :
145                                                                 AILocalizedString(@"Contact ID",nil)) stringByAppendingString:@":"]];   
148 - (IBAction)cancelBlockSheet:(id)sender
150     [NSApp endSheet:sheet];
153 - (void)addObject:(AIListContact *)inContact
155         if (![listContents containsObject:inContact]) {
156                 [listContents addObject:inContact];
157         }
158         
159         [inContact setIsOnPrivacyList:YES updateList:YES privacyType:(([self selectedPrivacyOption] == AIPrivacyOptionAllowUsers) ?
160                                                                                                                                   AIPrivacyTypePermit :
161                                                                                                                                   AIPrivacyTypeDeny)];  
164 - (IBAction)didBlockSheet:(id)sender
166         NSSet *contactArray = [self contactsFromTextField];
168         //Add the contact immediately
169         if (contactArray && [contactArray count]) {
170                 NSEnumerator *enumerator;
171                 AIListContact *contact;
172                 
173                 enumerator = [contactArray objectEnumerator];
174                 while ((contact = [enumerator nextObject])) {
175                         [self addObject:contact];
176                 }
177                 
178                 [table reloadData];
179         }
181     [NSApp endSheet:sheet];
185 - (void)didEndSheet:(NSWindow *)theSheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
187         [sheetAccountMenu release]; sheetAccountMenu = nil;
188     [theSheet orderOut:self];
192  * @brief Get a set of all contacts which are represented by the currently selected account and UID field
194  * @result A set of AIListContact objects
195  */
196 - (NSSet *)contactsFromTextField
198         AIListContact   *contact = nil;
199         NSString                *UID = nil;
200         AIAccount               *account = [[popUp_sheetAccounts selectedItem] representedObject];;
201         NSArray                 *accountArray;
202         NSMutableSet    *contactsSet = [NSMutableSet set];
203         NSEnumerator    *enumerator;
204         id                              impliedValue = [field impliedValue];
206         if (account) {
207                 accountArray = [NSArray arrayWithObject:account];
208         } else {
209                 //All accounts
210                 NSMutableArray  *tempArray = [NSMutableArray array];
211                 NSMenuItem              *menuItem;
212                 
213                 enumerator = [[[popUp_sheetAccounts menu] itemArray] objectEnumerator];
214                 while ((menuItem = [enumerator nextObject])) {
215                         AIAccount *anAccount;
216                         
217                         if ((anAccount = [menuItem representedObject])) {
218                                 [tempArray addObject:anAccount];
219                         }
220                 }
221                 
222                 accountArray = tempArray;
223         }
225         enumerator = [accountArray objectEnumerator];
226         while ((account = [enumerator nextObject])) {
227                 if ([impliedValue isKindOfClass:[AIMetaContact class]]) {
228                         AIListContact *containedContact;
229                         NSEnumerator *contactEnumerator = [[(AIMetaContact *)impliedValue listContactsIncludingOfflineAccounts] objectEnumerator];
230                         
231                         while ((containedContact = [contactEnumerator nextObject])) {
232                                 /* For each contact contained my the metacontact, check if its service class matches the current account's.
233                                  * If it does, add that contact to our list, using the contactController to get an AIListContact specific for the account.
234                                  */
235                                 if ([[[containedContact service] serviceClass] isEqualToString:[[account service] serviceClass]]) {
236                                         contact = [[adium contactController] contactWithService:[account service]
237                                                                                                                                         account:account
238                                                                                                                                                 UID:[containedContact UID]];
239                                         [contactsSet addObject:contact];
240                                 }
241                         }
242                         
243                 } else {
244                         if ([impliedValue isKindOfClass:[AIListContact class]]) {
245                                 UID = [(AIListContact *)impliedValue UID];
246                         
247                         } else  if ([impliedValue isKindOfClass:[NSString class]]) {
248                                 UID = [[account service] filterUID:impliedValue removeIgnoredCharacters:YES];
249                         }
250                         
251                         if (UID) {
252                                 //Get a contact with this UID on the current account
253                                 contact = [[adium contactController] contactWithService:[account service]
254                                                                                                                                 account:account 
255                                                                                                                                         UID:UID];
256                                 
257                                 [contactsSet addObject:contact];
258                         }
259                 }
260                         
261         }
262         
263         return contactsSet;
266 - (void)configureTextField
268         AIAccount *account = [[popUp_sheetAccounts selectedItem] representedObject];
269         NSEnumerator            *enumerator;
270     AIListContact               *contact;
271         
272         //Clear the completing strings
273         [field setCompletingStrings:nil];
274         
275         //Configure the auto-complete view to autocomplete for contacts matching the selected account's service
276     enumerator = [[[adium contactController] allContactsInGroup:nil subgroups:YES onAccount:nil] objectEnumerator];
277     while ((contact = [enumerator nextObject])) {
278                 if (!account ||
279                         [contact service] == [account service]) {
280                         NSString *UID = [contact UID];
281                         [field addCompletionString:[contact formattedUID] withImpliedCompletion:UID];
282                         [field addCompletionString:[contact displayName] withImpliedCompletion:UID];
283                         [field addCompletionString:UID];
284                 }
285     }
288 #pragma mark Removing a contact from the  list
290 - (IBAction)removeSelection:(id)sender
292         int selection = [[table selectedRowIndexes] firstIndex];
293         
294         if (selection != NSNotFound) {
295                 AIListContact *contact = [listContents objectAtIndex:selection];
297                 //Remove from our list
298                 [listContents removeObject:contact];
299                 [table reloadData];
301                 //Update serverside
302                 [contact setIsOnPrivacyList:NO updateList:YES privacyType:(([self selectedPrivacyOption] == AIPrivacyOptionAllowUsers) ?
303                                                                                                                                    AIPrivacyTypePermit :
304                                                                                                                                    AIPrivacyTypeDeny)];
305         }
308 - (void)tableViewDeleteSelectedRows:(NSTableView *)tableView
310         [self removeSelection:tableView];
313 - (void)setAccountColumnsVisible:(BOOL)visible
315         if (accountColumnsVisible != visible) {
316                 if (visible) {
317                         [table addTableColumn:accountCol];
318                 } else {
319                         [table removeTableColumn:accountCol];                   
320                 }
322                 [table sizeToFit];
323                 accountColumnsVisible = visible;
324         }
326 #pragma mark Privacy options menu
328 - (NSMenu *)privacyOptionsMenu
330         //build the menu of states
331         NSMenu *stateMenu = [[NSMenu alloc] init];
333         NSMenuItem *menuItem;
334         
335         menuItem = [[NSMenuItem alloc] initWithTitle:AILocalizedString(@"Allow anyone", nil) 
336                                                                                   action:NULL
337                                                                    keyEquivalent:@""];
338         [menuItem setTag:AIPrivacyOptionAllowAll];
339         [stateMenu addItem:menuItem];
340         [menuItem release];
342         menuItem = [[NSMenuItem alloc] initWithTitle:AILocalizedString(@"Allow only contacts on my contact list", nil) 
343                                                                                   action:NULL
344                                                                    keyEquivalent:@""];
345         [menuItem setTag:AIPrivacyOptionAllowContactList];
346         [stateMenu addItem:menuItem];
347         [menuItem release];
349         menuItem = [[NSMenuItem alloc] initWithTitle:AILocalizedString(@"Allow only certain contacts", nil) 
350                                                                                   action:NULL
351                                                                    keyEquivalent:@""];
352         [menuItem setTag:AIPrivacyOptionAllowUsers];
353         [stateMenu addItem:menuItem];
354         [menuItem release];
356         menuItem = [[NSMenuItem alloc] initWithTitle:AILocalizedString(@"Block certain contacts", nil) 
357                                                                                   action:NULL
358                                                                    keyEquivalent:@""];
359         [menuItem setTag:AIPrivacyOptionDenyUsers];
360         [stateMenu addItem:menuItem];
361         [menuItem release];
363         /*
364         tmpItem = [[NSMenuItem alloc] initWithTitle:AILocalizedString(@"Custom settings for each account", nil) action:NULL keyEquivalent:@""];
365         [tmpItem setRepresentedObject:[NSNumber numberWithInt:AIPrivacyOptionCustom]];
366         [stateMenu addItem:[tmpItem autorelease]];
367         */
369         return [stateMenu autorelease];
372 - (AIPrivacyOption)selectedPrivacyOption
374         return [[stateChooser selectedItem] tag];
378  * @brief Set a privacy option and update our view for it
380  * @param sender If nil, we update our display without attempting to change anything on our account
381  */
382 - (IBAction)setPrivacyOption:(id)sender
384         AIAccount<AIAccount_Privacy> *account = [self selectedAccount];
385         AIPrivacyOption privacyOption = [self selectedPrivacyOption];
387         //First, let's get the right tab view selected
388         switch (privacyOption) {
389                 case AIPrivacyOptionAllowAll:
390                 case AIPrivacyOptionAllowContactList:
391                 case AIPrivacyOptionCustom:
392                         if (![[[tabView_contactList selectedTabViewItem] identifier] isEqualToString:@"empty"]) {
393                                 [tabView_contactList selectTabViewItemWithIdentifier:@"empty"];
394                                 [tabView_contactList setHidden:YES];
396                                 NSRect frame = [[self window] frame];
397                                 float tabViewHeight = [tabView_contactList frame].size.height;
398                                 frame.size.height -= tabViewHeight;
399                                 frame.origin.y += tabViewHeight;
400                                 
401                                 //Don't resize vertically now...
402                                 [tabView_contactList setAutoresizingMask:NSViewWidthSizable];
404                                 [[self window] setMinSize:NSMakeSize(250, frame.size.height)];
405                                 [[self window] setMaxSize:NSMakeSize(FLT_MAX, frame.size.height)];
406                                 [[self window] setFrame:frame display:YES animate:YES];
407                         }
408                         break;
409                         
410                 case AIPrivacyOptionAllowUsers:
411                 case AIPrivacyOptionDenyUsers:
412                         if (![[[tabView_contactList selectedTabViewItem] identifier] isEqualToString:@"list"]) {
413                                 [tabView_contactList selectTabViewItemWithIdentifier:@"list"];
415                                 NSRect frame = [[self window] frame];
416                                 float tabViewHeight = [tabView_contactList frame].size.height;
417                                 frame.size.height += tabViewHeight;
418                                 frame.origin.y -= tabViewHeight;
419                                 
420                                 [[self window] setMinSize:NSMakeSize(250, 320)];
421                                 [[self window] setMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)];
422                                 
423                                 //Set frame after fixing our min/max size so the resize won't fail
424                                 [[self window] setFrame:frame display:YES animate:YES];
426                                 [tabView_contactList setHidden:NO];
428                                 //Allow resizing vertically again
429                                 [tabView_contactList setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
430                         }
431                         break;
432                 case AIPrivacyOptionDenyAll:
433                 case AIPrivacyOptionUnknown:
434                         NSLog(@"We should never see these...");
435                         break;
436         }
437         
438         if (sender) {
439                 if (account) {
440                         [account setPrivacyOptions:privacyOption];
441                         
442                 } else {
443                         NSEnumerator    *enumerator = [[[popUp_accounts menu] itemArray] objectEnumerator];
444                         NSMenuItem                                              *menuItem;
445                         AIAccount<AIAccount_Privacy>    *representedAccount;
447                         while ((menuItem = [enumerator nextObject])) {
448                                 if ((representedAccount = [menuItem representedObject])) {
449                                         [representedAccount setPrivacyOptions:privacyOption];
450                                 }
451                         }
452                 }
453         }
454         
455         //Now make our listContents array match the serverside arrays for the selected account(s)
456         [listContents removeAllObjects];
457         if ((privacyOption == AIPrivacyOptionAllowUsers) ||
458                 (privacyOption == AIPrivacyOptionDenyUsers)) {
459                 if (account) {
460                         [listContents addObjectsFromArray:[account listObjectsOnPrivacyList:((privacyOption == AIPrivacyOptionAllowUsers) ?
461                                                                                                                                                                  AIPrivacyTypePermit :
462                                                                                                                                                                  AIPrivacyTypeDeny)]];          
463                 } else {
464                         NSEnumerator                                    *enumerator = [[[popUp_accounts menu] itemArray] objectEnumerator];
465                         NSMenuItem                                              *menuItem;
466                         AIAccount<AIAccount_Privacy>    *representedAccount;
468                         while ((menuItem = [enumerator nextObject])) {
469                                 if ((representedAccount = [menuItem representedObject])) {
470                                         [listContents addObjectsFromArray:[representedAccount listObjectsOnPrivacyList:((privacyOption == AIPrivacyOptionAllowUsers) ?
471                                                                                                                                                                                                         AIPrivacyTypePermit :
472                                                                                                                                                                                                         AIPrivacyTypeDeny)]];           
473                                 }
474                         }
475                 }
476         }
478         [table reloadData];
481 - (void)selectPrivacyOption:(AIPrivacyOption)privacyOption
483         BOOL success = [stateChooser compatibleSelectItemWithTag:privacyOption];
484         if (privacyOption == AIPrivacyOptionCustom) {
485                 if (!success) {
486                         NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle:AILocalizedString(@"(Multiple privacy levels are active)", nil) 
487                                                                                                                           action:NULL
488                                                                                                            keyEquivalent:@""];
489                         [menuItem setTag:AIPrivacyOptionCustom];
490                         [[stateChooser menu] addItem:menuItem];
491                         [menuItem release];
492                         
493                         success = [stateChooser compatibleSelectItemWithTag:privacyOption];
494                 }
496         } else {
497                 //Not on custom; make sure custom isn't still in the menu
498                 int customItemIndex = [stateChooser indexOfItemWithTag:AIPrivacyOptionCustom];
499                 if (customItemIndex != -1) {
500                         [[stateChooser menu] removeItemAtIndex:customItemIndex];
501                 }
502         }
504         //Now update our view for this privacy option
505         [self setPrivacyOption:nil];
508 #pragma mark Account menu
510  * @brief Return the currently selected account, or nil if the 'All' item is selected
511  */
512 - (AIAccount<AIAccount_Privacy> *)selectedAccount
514         return [[popUp_accounts selectedItem] representedObject];
518  * @brief Action called when the account selection changes
520  * Update our view and the privacy option menu to be appropriate for the newly selected account.
521  * This may be called with a sender of nil by code elsewhere to force an update
522  */
523 - (void)accountMenu:(AIAccountMenu *)inAccountMenu didSelectAccount:(AIAccount *)inAccount
525         if (inAccountMenu == accountMenu) {
526                 AIAccount<AIAccount_Privacy> *account = [self selectedAccount];
527                 if (account) {
528                         //Selected an account
529                         AIPrivacyOption privacyOption = [account privacyOptions];
530                         
531                         //Don't need the account column when we're showing for just one account
532                         [self setAccountColumnsVisible:NO];
534                         [self selectPrivacyOption:privacyOption];                       
536                 } else {
537                         //Selected 'All'. We need to determine what privacy option to display for the set of all accounts.
538                         AIPrivacyOption currentState = AIPrivacyOptionUnknown;
539                         NSEnumerator    *enumerator = [[[popUp_accounts menu] itemArray] objectEnumerator];
540                         NSMenuItem              *menuItem;
541                         
542                         while ((menuItem = [enumerator nextObject])) {
543                                 if ((account = [menuItem representedObject])) {
544                                         AIPrivacyOption accountState = [account privacyOptions];
545                                         
546                                         if (currentState == AIPrivacyOptionUnknown) {
547                                                 //We don't know the state of an account yet
548                                                 currentState = accountState;
549                                         } else if (accountState != currentState) {
550                                                 currentState = AIPrivacyOptionCustom;
551                                         }                               
552                                 }
553                         }
554                         
555                         [self setAccountColumnsVisible:YES];
557                         [self selectPrivacyOption:currentState];
558                 }
560         } else if (inAccountMenu == sheetAccountMenu) {
561                 //Update our sheet for the current account
562                 [self selectAccountInSheet:inAccount];
563         }
567  * @brief The 'All' menu item for accounts was selected
569  * We simulate an AIAccountMenu delegate call, since the All item was added by RAFBLockEditorWindowController.
570  */
571 - (IBAction)selectedAllAccountItem:(id)sender
573         AIAccountMenu *relevantAccountMenu = (([sender menu] == [popUp_accounts menu]) ?
574                                                                                   accountMenu :
575                                                                                   sheetAccountMenu);
577         [self accountMenu:relevantAccountMenu didSelectAccount:nil];
581  * @brief Select an account in our account menu, then update everything else to be appropriate for it
582  */
583 - (void)selectAccount:(AIAccount *)inAccount
585         [popUp_accounts selectItemWithRepresentedObject:inAccount];
586         
587         [self accountMenu:accountMenu didSelectAccount:inAccount];
591  * @brief Add account menu items to our location
593  * Implemented as required by the AccountMenuPlugin protocol.
595  * @param menuItemArray An <tt>NSArray</tt> of <tt>NSMenuItem</tt> objects to be added to the menu
596  */
597 - (void)accountMenu:(AIAccountMenu *)inAccountMenu didRebuildMenuItems:(NSArray *)menuItems
599         AIAccount        *previouslySelectedAccount = nil;
600         NSEnumerator *enumerator;
601         NSMenuItem       *menuItem;
602         NSMenu           *menu = [[NSMenu alloc] init];
604         /*
605          * accountMenu isn't set the first time we get here as the accountMenu is created. Similarly, sheetAccountMenu isn't created its first time.
606          * This code makes the (true) assumption that accountMenu is _always_ created before sheetAccountMenu.
607          */     
608         BOOL isPrimaryAccountMenu = (!accountMenu || (inAccountMenu == accountMenu));
610         if (isPrimaryAccountMenu) {
611                 if ([popUp_accounts menu]) {
612                         previouslySelectedAccount = [[popUp_accounts selectedItem] representedObject];
613                 }
614         } else if (inAccountMenu == sheetAccountMenu) {
615                 if ([popUp_sheetAccounts menu]) {
616                         previouslySelectedAccount = [[popUp_sheetAccounts selectedItem] representedObject];
617                 }               
618         }
620         //Add the All menu item first if we have more than one account listed
621         if ([menuItems count] > 1) {
622                 [menu addItemWithTitle:AILocalizedString(@"All", nll)
623                                                 target:self
624                                                 action:@selector(selectedAllAccountItem:)
625                                  keyEquivalent:@""];
626         }
628         /*
629          * As we enumerate, we:
630          *      1) Determine what state the accounts within the menu are in
631          *  2) Add the menu items to our menu
632          */
633         enumerator = [menuItems objectEnumerator];
634         while ((menuItem = [enumerator nextObject])) {          
635                 [menu addItem:menuItem];
636         }
638         if (isPrimaryAccountMenu) {
639                 [popUp_accounts setMenu:menu];
641                 /* Restore the previous account selection if there was one.
642                  * Whether there was one or not, this will cause the rest of our view update to match the new/current selection
643                  */
644                 [self selectAccount:previouslySelectedAccount];
646         } else {
647                 [popUp_sheetAccounts setMenu:menu];
648                 
649                 [self selectAccountInSheet:previouslySelectedAccount];
650         }
652         [menu release];
655 - (BOOL)accountMenu:(AIAccountMenu *)inAccountMenu shouldIncludeAccount:(AIAccount *)inAccount
657         BOOL isPrimaryAccountMenu = (!accountMenu || (inAccountMenu == accountMenu));
659         if (isPrimaryAccountMenu) {
660                 return ([inAccount online] &&
661                                 [inAccount conformsToProtocol:@protocol(AIAccount_Privacy)]);
662         } else {
663                 AIAccount *selectedPrimaryAccount = [self selectedAccount];
664                 if (selectedPrimaryAccount) {
665                         //An account is selected in the main window; only incldue that account in our sheet
666                         return (inAccount == selectedPrimaryAccount);
668                 } else {
669                         //'All' is selected in the main window; include all accounts which are online and support privacy
670                         return ([inAccount online] &&
671                                         [inAccount conformsToProtocol:@protocol(AIAccount_Privacy)]);                   
672                 }
673         }
676 - (void)privacySettingsChangedExternally:(NSNotification *)inNotification
678         [self accountMenu:accountMenu didSelectAccount:[self selectedAccount]]; 
681 #pragma mark Table view
683 - (int)numberOfRowsInTableView:(NSTableView *)aTableView
685         return [listContents count];
688 - (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
690         NSString                *identifier = [aTableColumn identifier];
691         AIListContact   *contact = [listContents objectAtIndex:rowIndex];
693         if ([identifier isEqualToString:@"icon"]) {
694                 return [contact menuIcon];
695                 
696         } else if ([identifier isEqualToString:@"contact"]) {
697                 return [contact formattedUID];
699         } else if ([identifier isEqualToString:@"account"]) {
700                 return [[contact account] formattedUID];
701         }
702         
703         return nil;
706 //Below code is from RAFDragArrayController -- check to be sure it still applies here
707 - (BOOL)tableView:(NSTableView *)tv writeRows:(NSArray*)rows toPasteboard:(NSPasteboard*)pboard
709         //Begin the drag
710         if (dragItems != rows) {
711                 [dragItems release];
712                 dragItems = [rows retain];
713         }
714         
715         [pboard declareTypes:[NSArray arrayWithObjects:@"AIListObject",@"AIListObjectUniqueIDs",nil] owner:self];
716         [pboard setString:@"Private" forType:@"AIListObject"];
717         
718 #warning take this debug code out when we're sure this DnD operation stuff works
719         if (dragItems) {
720                 NSEnumerator    *enumerator = [dragItems objectEnumerator];
721                 AIListObject    *listObject;
722                 while ((listObject = [enumerator nextObject])) {
723                         NSLog(@"dragging %@",[listObject internalObjectID]);
724                 }
725         }
726         
727         
728         return YES;
731 - (void)pasteboard:(NSPasteboard *)sender provideDataForType:(NSString *)type
733         //Provide an array of internalObjectIDs which can be used to reference all the dragged contacts
734         if ([type isEqualToString:@"AIListObjectUniqueIDs"]) {
735                 
736                 if (dragItems) {
737                         NSMutableArray  *dragItemsArray = [NSMutableArray array];
738                         NSEnumerator    *enumerator = [dragItems objectEnumerator];
739                         AIListObject    *listObject;
740                         
741                         while ((listObject = [enumerator nextObject])) {
742                                 [dragItemsArray addObject:[listObject internalObjectID]];
743                         }
744                         
745                         [sender setPropertyList:dragItemsArray forType:@"AIListObjectUniqueIDs"];
746                 }
747         }
750 - (NSDragOperation)tableView:(NSTableView*)tv
751                                 validateDrop:(id <NSDraggingInfo>)info
752                                  proposedRow:(int)row
753            proposedDropOperation:(NSTableViewDropOperation)op
755     
756     NSDragOperation dragOp = NSDragOperationCopy;
757         
758     if ([info draggingSource] == table) {
759                 dragOp =  NSDragOperationMove;
760     }
761     [tv setDropRow:row dropOperation:NSTableViewDropAbove];
762         
763     return dragOp;
766 - (void)addListObjectToList:(AIListObject *)listObject
768         AIListObject *tmp;
769         NSEnumerator *groupEnum;
770         if ([listObject isMemberOfClass:[AIListGroup class]]) {
771                 groupEnum = [[(AIListGroup *)listObject listContacts] objectEnumerator];
772                 while ((tmp = [groupEnum nextObject]))
773                         [self addListObjectToList:tmp];
774         } else if ([listObject isMemberOfClass:[AIMetaContact class]]) {
775                 groupEnum = [[(AIMetaContact *)listObject listContacts] objectEnumerator];
776                 while ((tmp = [groupEnum nextObject]))
777                         [self addListObjectToList:tmp];
778         } else if ([listObject isMemberOfClass:[AIListContact class]]) {
779                 //if the account for this contact is connected...
780                 if ([[[(AIListContact *)listObject account] statusObjectForKey:@"Online"] boolValue])
781                         [self addObject:(AIListContact *)listObject];
782         }
785 - (BOOL)tableView:(NSTableView*)tv acceptDrop:(id <NSDraggingInfo>)info row:(int)row dropOperation:(NSTableViewDropOperation)op
787         BOOL accept = NO;
788     if (row < 0)
789                 row = 0;
790         
791         if ([[[info draggingPasteboard] types] containsObject:@"AIListObjectUniqueIDs"]) {
792                 NSArray                 *dragItemsUniqueIDs = [[info draggingPasteboard] propertyListForType:@"AIListObjectUniqueIDs"];
793                 NSString *uniqueUID;
794                 NSEnumerator *idEnumerator = [dragItemsUniqueIDs objectEnumerator];
795                 while ((uniqueUID = [idEnumerator nextObject]))
796                         [self addListObjectToList:[[adium contactController] existingListObjectWithUniqueID:uniqueUID]];
797                 accept = YES;
798         }
799         
800     return accept;
803 @end