Bug Summary

File:Source/RAFBlockEditorWindowController.m
Location:line 521, column 4
Description:dead store

Annotated Source Code

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//
8
9#import "RAFBlockEditorWindowController.h"
10#import <Adium/AIAccountControllerProtocol.h>
11#import <Adium/AIContactControllerProtocol.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>
20
21@interface RAFBlockEditorWindowController (PRIVATE)
22- (NSMenu *)privacyOptionsMenu;
23- (AIAccount<AIAccount_Privacy> *)selectedAccount;
24- (void)configureTextField;
25- (NSSet *)contactsFromTextField;
26- (AIPrivacyOption)selectedPrivacyOption;
27@end
28
29@implementation RAFBlockEditorWindowController
30
31static RAFBlockEditorWindowController *sharedInstance = nil0;
32
33+ (void)showWindow
34{
35 if (!sharedInstance) {
36 sharedInstance = [[self alloc] initWithWindowNibName:@"BlockEditorWindow"];
37 }
38
39 [sharedInstance showWindow:nil0];
40 [[sharedInstance window] makeKeyAndOrderFront:nil0];
41}
42
43- (void)windowDidLoad
44{
45 [[self window] setTitle:AILocalizedString[ [ NSBundle bundleForClass : [ self class ] ] localizedStringForKey
: ( @ "Privacy Settings" ) value : @ "" table : ( 0 ) ]
(@"Privacy Settings", nil)];
46 [cancelButton setLocalizedString:AILocalizedString[ [ NSBundle bundleForClass : [ self class ] ] localizedStringForKey
: ( @ "Cancel" ) value : @ "" table : ( 0 ) ]
(@"Cancel","Cancel button for Privacy Settings")];
47 [blockButton setLocalizedString:AILocalizedString[ [ NSBundle bundleForClass : [ self class ] ] localizedStringForKey
: ( @ "Add" ) value : @ "" table : ( 0 ) ]
(@"Add","Add button for Privacy Settings")];
48 [[buddyCol headerCell] setTitle:AILocalizedString[ [ NSBundle bundleForClass : [ self class ] ] localizedStringForKey
: ( @ "Contact" ) value : @ "" table : ( 0 ) ]
(@"Contact","Title of column containing user IDs of blocked contacts")];
49 [[accountCol headerCell] setTitle:AILocalizedString[ [ NSBundle bundleForClass : [ self class ] ] localizedStringForKey
: ( @ "Account" ) value : @ "" table : ( 0 ) ]
(@"Account","Title of column containing blocking accounts")];
50 [accountText setLocalizedString:AILocalizedString[ [ NSBundle bundleForClass : [ self class ] ] localizedStringForKey
: ( @ "Account:" ) value : @ "" table : ( 0 ) ]
(@"Account:",nil)];
51
52 {
53 //Let the min X margin be resizeable while label_account and label_privacyLevel localize in case the window moves
54 [stateChooser setAutoresizingMask:(NSViewMinYMargin | NSViewMinXMargin)];
55 [popUp_accounts setAutoresizingMask:(NSViewMinYMargin | NSViewMinXMargin)];
56
57 //Keep label_privacyLevel in place, too, while label_account potentially resizes the window
58 [label_privacyLevel setAutoresizingMask:(NSViewMinYMargin | NSViewMinXMargin)];
59 [label_account setLocalizedString:AILocalizedString[ [ NSBundle bundleForClass : [ self class ] ] localizedStringForKey
: ( @ "Account:" ) value : @ "" table : ( 0 ) ]
(@"Account:",nil)];
60 [label_privacyLevel setAutoresizingMask:(NSViewMinYMargin | NSViewMaxXMargin)];
61 //Account is in place; popUp_accounts can width-resize again
62 [popUp_accounts setAutoresizingMask:(NSViewWidthSizable | NSViewMinYMargin)];
63
64 [label_privacyLevel setLocalizedString:AILocalizedString[ [ NSBundle bundleForClass : [ self class ] ] localizedStringForKey
: ( @ "Privacy level:" ) value : @ "" table : ( 0 ) ]
(@"Privacy level:", nil)];
65 [stateChooser setAutoresizingMask:(NSViewWidthSizable | NSViewMinYMargin)];
66 }
67
68 accountColumnsVisible = YES( BOOL ) 1;
69 [accountCol retain];
70
71 listContents = [[NSMutableArray alloc] init];
72
73 [stateChooser setMenu:[self privacyOptionsMenu]];
74
75 [[table tableColumnWithIdentifier:@"icon"] setDataCell:[[[NSImageCell alloc] init] autorelease]];
76
77 accountMenu = [[AIAccountMenu accountMenuWithDelegate:self
78 submenuType:AIAccountNoSubmenu
79 showTitleVerbs:NO( BOOL ) 0] retain];
80 [table registerForDraggedTypes:[NSArray arrayWithObjects:@"AIListObject", @"AIListObjectUniqueIDs",nil0]];
81
82 [[adium notificationCenter] addObserver:self
83 selector:@selector(privacySettingsChangedExternally:)
84 name:@"AIPrivacySettingsChangedOutsideOfPrivacyWindow"
85 object:nil0];
86
87 [[adium contactController] registerListObjectObserver:self];
88
89 [super windowDidLoad];
90}
91
92- (void)windowWillClose:(id)sender
93{
94 [super windowWillClose:sender];
95
96 [[adium contactController] unregisterListObjectObserver:self];
97
98 [[adium notificationCenter] removeObserver:self];
99 [sharedInstance release]; sharedInstance = nil0;
100}
101
102- (NSString *)adiumFrameAutosaveName
103{
104 return @"PrivacyWindow";
105}
106
107- (void)dealloc
108{
109 [accountCol release];
110 [accountMenu release];
111 [listContents release];
112 [listContentsAllAccounts release];
113
114 [super dealloc];
115}
116
117- (NSMutableArray*)listContents
118{
119 return listContents;
120}
121
122- (void)setListContents:(NSArray*)newList
123{
124 if (newList != listContents) {
125 [listContents release];
126 listContents = [newList mutableCopy];
127 }
128}
129
130#pragma mark Adding a contact to the list
131
132- (void)selectAccountInSheet:(AIAccount *)inAccount
133{
134 [popUp_sheetAccounts selectItemWithRepresentedObject:inAccount];
135 [self configureTextField];
136
137 NSString *userNameLabel = [[inAccount service] userNameLabel];
138
139 [accountText setAutoresizingMask:NSViewMinXMargin];
140 [buddyText setLocalizedString:[(userNameLabel ?
141 userNameLabel : AILocalizedString[ [ NSBundle bundleForClass : [ self class ] ] localizedStringForKey
: ( @ "Contact ID" ) value : @ "" table : ( 0 ) ]
(@"Contact ID",nil)) stringByAppendingString:AILocalizedString[ [ NSBundle bundleForClass : [ self class ] ] localizedStringForKey
: ( @ ":" ) value : @ "" table : ( 0 ) ]
(@":", "Colon which will be appended after a label such as 'User Name', before an input field")]];
142 [accountText setAutoresizingMask:NSViewMaxXMargin];
143}
144
145- (IBActionvoid)runBlockSheet:(id)sender
146{
147 [field setStringValue:@""];
148
149 sheetAccountMenu = [[AIAccountMenu accountMenuWithDelegate:self
150 submenuType:AIAccountNoSubmenu
151 showTitleVerbs:NO( BOOL ) 0] retain];
152 [self selectAccountInSheet:[[popUp_sheetAccounts selectedItem] representedObject]];
153
154 [NSApp beginSheet:sheet
155 modalForWindow:[self window]
156 modalDelegate:self
157 didEndSelector:@selector(didEndSheet:returnCode:contextInfo:)
158 contextInfo:nil0];
159}
160
161
162- (IBActionvoid)cancelBlockSheet:(id)sender
163{
164 [NSApp endSheet:sheet];
165}
166
167- (void)addObject:(AIListContact *)inContact
168{
169 if (inContact) {
170 if (![listContents containsObject:inContact]) {
171 [listContents addObject:inContact];
172 }
173
174 [inContact setIsOnPrivacyList:YES( BOOL ) 1 updateList:YES( BOOL ) 1 privacyType:(([self selectedPrivacyOption] == AIPrivacyOptionAllowUsers) ?
175 AIPrivacyTypePermit :
176 AIPrivacyTypeDeny)];
177 }
178}
179
180- (IBActionvoid)didBlockSheet:(id)sender
181{
182 NSSet *contactArray = [self contactsFromTextField];
183
184 //Add the contact immediately
185 if (contactArray && [contactArray count]) {
186 NSEnumerator *enumerator;
187 AIListContact *contact;
188
189 enumerator = [contactArray objectEnumerator];
190 while ((contact = [enumerator nextObject])) {
191 [self addObject:contact];
192 }
193
194 [table reloadData];
195 }
196
197 [NSApp endSheet:sheet];
198}
199
200
201- (void)didEndSheet:(NSWindow *)theSheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
202{
203 [sheetAccountMenu release]; sheetAccountMenu = nil0;
204 [theSheet orderOut:self];
205}
206
207/*!
208 * @brief Get a set of all contacts which are represented by the currently selected account and UID field
209 *
210 * @result A set of AIListContact objects
211 */
212- (NSSet *)contactsFromTextField
213{
214 AIListContact *contact = nil0;
215 NSString *UID = nil0;
216 AIAccount *account = [[popUp_sheetAccounts selectedItem] representedObject];;
217 NSArray *accountArray;
218 NSMutableSet *contactsSet = [NSMutableSet set];
219 NSEnumerator *enumerator;
220 id impliedValue = [field impliedValue];
221
222 if (account) {
223 accountArray = [NSArray arrayWithObject:account];
224 } else {
225 //All accounts
226 NSMutableArray *tempArray = [NSMutableArray array];
227 NSMenuItem *menuItem;
228
229 enumerator = [[[popUp_sheetAccounts menu] itemArray] objectEnumerator];
230 while ((menuItem = [enumerator nextObject])) {
231 AIAccount *anAccount;
232
233 if ((anAccount = [menuItem representedObject])) {
234 [tempArray addObject:anAccount];
235 }
236 }
237
238 accountArray = tempArray;
239 }
240
241 enumerator = [accountArray objectEnumerator];
242 while ((account = [enumerator nextObject])) {
243 if ([impliedValue isKindOfClass:[AIMetaContact class]]) {
244 AIListContact *containedContact;
245 NSEnumerator *contactEnumerator = [[(AIMetaContact *)impliedValue listContactsIncludingOfflineAccounts] objectEnumerator];
246
247 while ((containedContact = [contactEnumerator nextObject])) {
248 /* For each contact contained my the metacontact, check if its service class matches the current account's.
249 * If it does, add that contact to our list, using the contactController to get an AIListContact specific for the account.
250 */
251 if ([[[containedContact service] serviceClass] isEqualToString:[[account service] serviceClass]]) {
252 if ((contact = [[adium contactController] contactWithService:[account service]
253 account:account
254 UID:[containedContact UID]])) {
255 [contactsSet addObject:contact];
256 }
257 }
258 }
259
260 } else {
261 if ([impliedValue isKindOfClass:[AIListContact class]]) {
262 UID = [(AIListContact *)impliedValue UID];
263
264 } else if ([impliedValue isKindOfClass:[NSString class]]) {
265 UID = [[account service] normalizeUID:impliedValue removeIgnoredCharacters:YES( BOOL ) 1];
266 }
267
268 if (UID) {
269 //Get a contact with this UID on the current account
270 if ((contact = [[adium contactController] contactWithService:[account service]
271 account:account
272 UID:UID])) {
273 [contactsSet addObject:contact];
274 }
275 }
276 }
277
278 }
279
280 return contactsSet;
281}
282
283- (void)configureTextField
284{
285 AIAccount *account = [[popUp_sheetAccounts selectedItem] representedObject];
286 NSEnumerator *enumerator;
287 AIListContact *contact;
288
289 //Clear the completing strings
290 [field setCompletingStrings:nil0];
291
292 //Configure the auto-complete view to autocomplete for contacts matching the selected account's service
293 enumerator = [[[adium contactController] allContacts] objectEnumerator];
294 while ((contact = [enumerator nextObject])) {
295 if (!account ||
296 [contact service] == [account service]) {
297 NSString *UID = [contact UID];
298 [field addCompletionString:[contact formattedUID] withImpliedCompletion:UID];
299 [field addCompletionString:[contact displayName] withImpliedCompletion:UID];
300 [field addCompletionString:UID];
301 }
302 }
303}
304
305#pragma mark Removing a contact from the list
306
307- (IBActionvoid)removeSelection:(id)sender
308{
309 NSIndexSet *selectedItems = [table selectedRowIndexes];
310
311 // If there's anything selected..
312 if ([selectedItems count]) {
313 AIListContact *contact;
314
315 // Iterate through the selected rows (backwards)
316 for (int selection = [selectedItems lastIndex]; selection != NSNotFound; selection = [selectedItems indexLessThanIndex:selection]) {
317 contact = [listContents objectAtIndex:selection];
318 // Remove from the serverside list
319 [contact setIsOnPrivacyList:NO( BOOL ) 0 updateList:YES( BOOL ) 1 privacyType:(([self selectedPrivacyOption] == AIPrivacyOptionAllowUsers) ?
320 AIPrivacyTypePermit :
321 AIPrivacyTypeDeny)];
322 [listContents removeObject:contact];
323 }
324
325 [table reloadData];
326 [table deselectAll:nil0];
327 }
328
329}
330
331- (void)tableViewDeleteSelectedRows:(NSTableView *)tableView
332{
333 [self removeSelection:tableView];
334}
335
336- (void)setAccountColumnsVisible:(BOOL)visible
337{
338 if (accountColumnsVisible != visible) {
339 if (visible) {
340 [table addTableColumn:accountCol];
341 } else {
342 [table removeTableColumn:accountCol];
343 }
344
345 [table sizeToFit];
346 accountColumnsVisible = visible;
347 }
348}
349#pragma mark Privacy options menu
350
351- (NSMenu *)privacyOptionsMenu
352{
353 //build the menu of states
354 NSMenu *stateMenu = [[NSMenu alloc] init];
355
356 NSMenuItem *menuItem;
357
358 menuItem = [[NSMenuItem alloc] initWithTitle:AILocalizedString[ [ NSBundle bundleForClass : [ self class ] ] localizedStringForKey
: ( @ "Allow anyone" ) value : @ "" table : ( 0 ) ]
(@"Allow anyone", nil)
359 action:NULL( ( void * ) 0 )
360 keyEquivalent:@""];
361 [menuItem setTag:AIPrivacyOptionAllowAll];
362 [stateMenu addItem:menuItem];
363 [menuItem release];
364
365 menuItem = [[NSMenuItem alloc] initWithTitle:AILocalizedString[ [ NSBundle bundleForClass : [ self class ] ] localizedStringForKey
: ( @ "Allow only contacts on my contact list" ) value : @ ""
table : ( 0 ) ]
(@"Allow only contacts on my contact list", nil)
366 action:NULL( ( void * ) 0 )
367 keyEquivalent:@""];
368 [menuItem setTag:AIPrivacyOptionAllowContactList];
369 [stateMenu addItem:menuItem];
370 [menuItem release];
371
372 menuItem = [[NSMenuItem alloc] initWithTitle:AILocalizedString[ [ NSBundle bundleForClass : [ self class ] ] localizedStringForKey
: ( @ "Allow only certain contacts" ) value : @ "" table : (
0 ) ]
(@"Allow only certain contacts", nil)
373 action:NULL( ( void * ) 0 )
374 keyEquivalent:@""];
375 [menuItem setTag:AIPrivacyOptionAllowUsers];
376 [stateMenu addItem:menuItem];
377 [menuItem release];
378
379 menuItem = [[NSMenuItem alloc] initWithTitle:AILocalizedString[ [ NSBundle bundleForClass : [ self class ] ] localizedStringForKey
: ( @ "Block certain contacts" ) value : @ "" table : ( 0 ) ]
(@"Block certain contacts", nil)
380 action:NULL( ( void * ) 0 )
381 keyEquivalent:@""];
382 [menuItem setTag:AIPrivacyOptionDenyUsers];
383 [stateMenu addItem:menuItem];
384 [menuItem release];
385
386 /*
387 tmpItem = [[NSMenuItem alloc] initWithTitle:AILocalizedString(@"Custom settings for each account", nil) action:NULL keyEquivalent:@""];
388 [tmpItem setRepresentedObject:[NSNumber numberWithInt:AIPrivacyOptionCustom]];
389 [stateMenu addItem:[tmpItem autorelease]];
390 */
391
392 return [stateMenu autorelease];
393}
394
395- (AIPrivacyOption)selectedPrivacyOption
396{
397 return [[stateChooser selectedItem] tag];
398}
399
400/*!
401 * @brief Set a privacy option and update our view for it
402 *
403 * @param sender If nil, we update our display without attempting to change anything on our account
404 */
405- (IBActionvoid)setPrivacyOption:(id)sender
406{
407 AIAccount<AIAccount_Privacy> *account = [self selectedAccount];
408 AIPrivacyOption privacyOption = [self selectedPrivacyOption];
409
410 //First, let's get the right tab view selected
411 switch (privacyOption) {
412 case AIPrivacyOptionAllowAll:
413 case AIPrivacyOptionAllowContactList:
414 case AIPrivacyOptionCustom:
415 if (![[[tabView_contactList selectedTabViewItem] identifier] isEqualToString:@"empty"]) {
416 [tabView_contactList selectTabViewItemWithIdentifier:@"empty"];
417 [tabView_contactList setHidden:YES( BOOL ) 1];
418
419 NSRect frame = [[self window] frame];
420 float tabViewHeight = [tabView_contactList frame].size.height;
421 frame.size.height -= tabViewHeight;
422 frame.origin.y += tabViewHeight;
423
424 //Don't resize vertically now...
425 [tabView_contactList setAutoresizingMask:NSViewWidthSizable];
426
427 [[self window] setMinSize:NSMakeSize(250, frame.size.height)];
428 [[self window] setMaxSize:NSMakeSize(FLT_MAX3.40282347e+38F, frame.size.height)];
429
430 AILog(@"Because of privacy option %i, resizing from %@ to %@",privacyOption,
431 NSStringFromRect([[self window] frame]),NSStringFromRect(frame));
432 [[self window] setFrame:frame display:YES( BOOL ) 1 animate:YES( BOOL ) 1];
433 }
434 break;
435
436 case AIPrivacyOptionAllowUsers:
437 case AIPrivacyOptionDenyUsers:
438 if (![[[tabView_contactList selectedTabViewItem] identifier] isEqualToString:@"list"]) {
439 [tabView_contactList selectTabViewItemWithIdentifier:@"list"];
440
441 NSRect frame = [[self window] frame];
442 float tabViewHeight = [tabView_contactList frame].size.height;
443 frame.size.height += tabViewHeight;
444 frame.origin.y -= tabViewHeight;
445
446 [[self window] setMinSize:NSMakeSize(250, 320)];
447 [[self window] setMaxSize:NSMakeSize(FLT_MAX3.40282347e+38F, FLT_MAX3.40282347e+38F)];
448
449 //Set frame after fixing our min/max size so the resize won't fail
450 AILog(@"Because of privacy option %i, resizing from %@ to %@",privacyOption,
451 NSStringFromRect([[self window] frame]),NSStringFromRect(frame));
452 [[self window] setFrame:frame display:YES( BOOL ) 1 animate:YES( BOOL ) 1];
453
454 [tabView_contactList setHidden:NO( BOOL ) 0];
455
456 //Allow resizing vertically again
457 [tabView_contactList setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
458 }
459 break;
460 case AIPrivacyOptionDenyAll:
461 case AIPrivacyOptionUnknown:
462 NSLog(@"We should never see these...");
463 break;
464 }
465
466 if (sender) {
467 if (account) {
468 [account setPrivacyOptions:privacyOption];
469
470 } else {
471 NSEnumerator *enumerator = [[[popUp_accounts menu] itemArray] objectEnumerator];
472 NSMenuItem *menuItem;
473 AIAccount<AIAccount_Privacy> *representedAccount;
474
475 while ((menuItem = [enumerator nextObject])) {
476 if ((representedAccount = [menuItem representedObject])) {
477 [representedAccount setPrivacyOptions:privacyOption];
478 }
479 }
480 }
481 }
482
483 //Now make our listContents array match the serverside arrays for the selected account(s)
484 [listContents removeAllObjects];
485 if ((privacyOption == AIPrivacyOptionAllowUsers) ||
486 (privacyOption == AIPrivacyOptionDenyUsers)) {
487 if (account) {
488 [listContents addObjectsFromArray:[account listObjectsOnPrivacyList:((privacyOption == AIPrivacyOptionAllowUsers) ?
489 AIPrivacyTypePermit :
490 AIPrivacyTypeDeny)]];
491 } else {
492 NSEnumerator *enumerator = [[[popUp_accounts menu] itemArray] objectEnumerator];
493 NSMenuItem *menuItem;
494 AIAccount<AIAccount_Privacy> *representedAccount;
495
496 while ((menuItem = [enumerator nextObject])) {
497 if ((representedAccount = [menuItem representedObject])) {
498 [listContents addObjectsFromArray:[representedAccount listObjectsOnPrivacyList:((privacyOption == AIPrivacyOptionAllowUsers) ?
499 AIPrivacyTypePermit :
500 AIPrivacyTypeDeny)]];
501 }
502 }
503 }
504 }
505
506 [table reloadData];
507}
508
509- (void)selectPrivacyOption:(AIPrivacyOption)privacyOption
510{
511 BOOL success = [stateChooser compatibleSelectItemWithTag:privacyOption];
512 if (privacyOption == AIPrivacyOptionCustom) {
513 if (!success) {
514 NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle:AILocalizedString[ [ NSBundle bundleForClass : [ self class ] ] localizedStringForKey
: ( @ "(Multiple privacy levels are active)" ) value : @ "" table
: ( 0 ) ]
(@"(Multiple privacy levels are active)", nil)
515 action:NULL( ( void * ) 0 )
516 keyEquivalent:@""];
517 [menuItem setTag:AIPrivacyOptionCustom];
518 [[stateChooser menu] addItem:menuItem];
519 [menuItem release];
520
Value stored to 'success' is never read
521 success = [stateChooser compatibleSelectItemWithTag:privacyOption];
522 }
523
524 } else {
525 //Not on custom; make sure custom isn't still in the menu
526 int customItemIndex = [stateChooser indexOfItemWithTag:AIPrivacyOptionCustom];
527 if (customItemIndex != -1) {
528 [[stateChooser menu] removeItemAtIndex:customItemIndex];
529 }
530 }
531
532 //Now update our view for this privacy option
533 [self setPrivacyOption:nil0];
534}
535
536#pragma mark Account menu
537/*!
538 * @brief Return the currently selected account, or nil if the 'All' item is selected
539 */
540- (AIAccount<AIAccount_Privacy> *)selectedAccount
541{
542 return [[popUp_accounts selectedItem] representedObject];
543}
544
545/*!
546 * @brief Action called when the account selection changes
547 *
548 * Update our view and the privacy option menu to be appropriate for the newly selected account.
549 * This may be called with a sender of nil by code elsewhere to force an update
550 */
551- (void)accountMenu:(AIAccountMenu *)inAccountMenu didSelectAccount:(AIAccount *)inAccount
552{
553 if (inAccountMenu == accountMenu) {
554 AIAccount<AIAccount_Privacy> *account = [self selectedAccount];
555 if (account) {
556 //Selected an account
557 AIPrivacyOption privacyOption = [account privacyOptions];
558
559 //Don't need the account column when we're showing for just one account
560 [self setAccountColumnsVisible:NO( BOOL ) 0];
561
562 [self selectPrivacyOption:privacyOption];
563
564 } else {
565 //Selected 'All'. We need to determine what privacy option to display for the set of all accounts.
566 AIPrivacyOption currentState = AIPrivacyOptionUnknown;
567 NSEnumerator *enumerator = [[[popUp_accounts menu] itemArray] objectEnumerator];
568 NSMenuItem *menuItem;
569
570 while ((menuItem = [enumerator nextObject])) {
571 if ((account = [menuItem representedObject])) {
572 AIPrivacyOption accountState = [account privacyOptions];
573
574 if (currentState == AIPrivacyOptionUnknown) {
575 //We don't know the state of an account yet
576 currentState = accountState;
577 } else if (accountState != currentState) {
578 currentState = AIPrivacyOptionCustom;
579 }
580 }
581 }
582
583 [self setAccountColumnsVisible:YES( BOOL ) 1];
584
585 [self selectPrivacyOption:currentState];
586 }
587
588 } else if (inAccountMenu == sheetAccountMenu) {
589 //Update our sheet for the current account
590 [self selectAccountInSheet:inAccount];
591 }
592}
593
594/*!
595 * @brief The 'All' menu item for accounts was selected
596 *
597 * We simulate an AIAccountMenu delegate call, since the All item was added by RAFBLockEditorWindowController.
598 */
599- (IBActionvoid)selectedAllAccountItem:(id)sender
600{
601 AIAccountMenu *relevantAccountMenu = (([sender menu] == [popUp_accounts menu]) ?
602 accountMenu :
603 sheetAccountMenu);
604
605 [self accountMenu:relevantAccountMenu didSelectAccount:nil0];
606}
607
608/*!
609 * @brief Select an account in our account menu, then update everything else to be appropriate for it
610 */
611- (void)selectAccount:(AIAccount *)inAccount
612{
613 [popUp_accounts selectItemWithRepresentedObject:inAccount];
614
615 [self accountMenu:accountMenu didSelectAccount:inAccount];
616}
617
618/*!
619 * @brief Add account menu items to our location
620 *
621 * Implemented as required by the AccountMenuPlugin protocol.
622 *
623 * @param menuItemArray An <tt>NSArray</tt> of <tt>NSMenuItem</tt> objects to be added to the menu
624 */
625- (void)accountMenu:(AIAccountMenu *)inAccountMenu didRebuildMenuItems:(NSArray *)menuItems
626{
627 AIAccount *previouslySelectedAccount = nil0;
628 NSEnumerator *enumerator;
629 NSMenuItem *menuItem;
630 NSMenu *menu = [[NSMenu alloc] init];
631
632 /*
633 * accountMenu isn't set the first time we get here as the accountMenu is created. Similarly, sheetAccountMenu isn't created its first time.
634 * This code makes the (true) assumption that accountMenu is _always_ created before sheetAccountMenu.
635 */
636 BOOL isPrimaryAccountMenu = (!accountMenu || (inAccountMenu == accountMenu));
637
638 if (isPrimaryAccountMenu) {
639 if ([popUp_accounts menu]) {
640 previouslySelectedAccount = [[popUp_accounts selectedItem] representedObject];
641 }
642 } else if (inAccountMenu == sheetAccountMenu) {
643 if ([popUp_sheetAccounts menu]) {
644 previouslySelectedAccount = [[popUp_sheetAccounts selectedItem] representedObject];
645 }
646 }
647
648 //Add the All menu item first if we have more than one account listed
649 if ([menuItems count] > 1) {
650 [menu addItemWithTitle:AILocalizedString[ [ NSBundle bundleForClass : [ self class ] ] localizedStringForKey
: ( @ "All" ) value : @ "" table : ( 0 ) ]
(@"All", nll)
651 target:self
652 action:@selector(selectedAllAccountItem:)
653 keyEquivalent:@""];
654 }
655
656 /*
657 * As we enumerate, we:
658 * 1) Determine what state the accounts within the menu are in
659 * 2) Add the menu items to our menu
660 */
661 enumerator = [menuItems objectEnumerator];
662 while ((menuItem = [enumerator nextObject])) {
663 [menu addItem:menuItem];
664 }
665
666 if (isPrimaryAccountMenu) {
667 [popUp_accounts setMenu:menu];
668
669 /* Restore the previous account selection if there was one.
670 * Whether there was one or not, this will cause the rest of our view update to match the new/current selection
671 */
672 [self selectAccount:previouslySelectedAccount];
673
674 } else {
675 [popUp_sheetAccounts setMenu:menu];
676
677 [self selectAccountInSheet:previouslySelectedAccount];
678 }
679
680 [menu release];
681}
682
683- (BOOL)accountMenu:(AIAccountMenu *)inAccountMenu shouldIncludeAccount:(AIAccount *)inAccount
684{
685 BOOL isPrimaryAccountMenu = (!accountMenu || (inAccountMenu == accountMenu));
686
687 if (isPrimaryAccountMenu) {
688 return ([inAccount online] &&
689 [inAccount conformsToProtocol:@protocol(AIAccount_Privacy)]);
690 } else {
691 AIAccount *selectedPrimaryAccount = [self selectedAccount];
692 if (selectedPrimaryAccount) {
693 //An account is selected in the main window; only incldue that account in our sheet
694 return (inAccount == selectedPrimaryAccount);
695
696 } else {
697 //'All' is selected in the main window; include all accounts which are online and support privacy
698 return ([inAccount online] &&
699 [inAccount conformsToProtocol:@protocol(AIAccount_Privacy)]);
700 }
701 }
702}
703
704- (void)privacySettingsChangedExternally:(NSNotification *)inNotification
705{
706 [self accountMenu:accountMenu didSelectAccount:[self selectedAccount]];
707}
708
709- (NSSet *)updateListObject:(AIListObject *)inObject keys:(NSSet *)inModifiedKeys silent:(BOOL)silent
710{
711 if ([inModifiedKeys containsObject:KEY_IS_BLOCKED@ "isBlocked"]) {
712 [self privacySettingsChangedExternally:nil0];
713 }
714
715 return nil0;
716}
717
718#pragma mark Table view
719
720- (int)numberOfRowsInTableView:(NSTableView *)aTableView
721{
722 return [listContents count];
723}
724
725- (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
726{
727 NSString *identifier = [aTableColumn identifier];
728 AIListContact *contact = [listContents objectAtIndex:rowIndex];
729
730 if ([identifier isEqualToString:@"icon"]) {
731 return [contact menuIcon];
732
733 } else if ([identifier isEqualToString:@"contact"]) {
734 return [contact formattedUID];
735
736 } else if ([identifier isEqualToString:@"account"]) {
737 return [[contact account] formattedUID];
738 }
739
740 return nil0;
741}
742
743- (BOOL)writeListObjects:(NSArray *)inArray toPasteboard:(NSPasteboard*)pboard
744{
745 [pboard declareTypes:[NSArray arrayWithObjects:@"AIListObject",@"AIListObjectUniqueIDs",nil0] owner:self];
746 [pboard setString:@"Private" forType:@"AIListObject"];
747
748 if (dragItems != inArray) {
749 [dragItems release];
750 dragItems = [inArray retain];
751 }
752
753 return YES( BOOL ) 1;
754}
755
756- (BOOL)tableView:(NSTableView *)tv writeRows:(NSArray*)rows toPasteboard:(NSPasteboard*)pboard
757{
758 NSMutableArray *itemArray = [NSMutableArray array];
759 NSEnumerator *enumerator = [rows objectEnumerator];
760 NSNumber *rowNumber;
761 while ((rowNumber = [enumerator nextObject])) {
762 [itemArray addObject:[listContents objectAtIndex:[rowNumber intValue]]];
763 }
764
765 return [self writeListObjects:itemArray toPasteboard:pboard];
766}
767
768- (BOOL)tableView:(NSTableView *)aTableView writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard*)pboard
769{
770 NSMutableArray *itemArray = [NSMutableArray array];
771 id item;
772
773 unsigned int bufSize = [rowIndexes count];
774 unsigned int *buf = malloc(bufSize * sizeof(unsigned int));
775 unsigned int i;
776
777 NSRange range = NSMakeRange([rowIndexes firstIndex], ([rowIndexes lastIndex]-[rowIndexes firstIndex]) + 1);
778 [rowIndexes getIndexes:buf maxCount:bufSize inIndexRange:&range];
779
780 for (i = 0; i != bufSize; i++) {
781 if ((item = [listContents objectAtIndex:buf[i]])) {
782 [itemArray addObject:item];
783 }
784 }
785
786 free(buf);
787
788 return [self writeListObjects:itemArray toPasteboard:pboard];
789}
790
791- (void)pasteboard:(NSPasteboard *)sender provideDataForType:(NSString *)type
792{
793 //Provide an array of internalObjectIDs which can be used to reference all the dragged contacts
794 if ([type isEqualToString:@"AIListObjectUniqueIDs"]) {
795
796 if (dragItems) {
797 NSMutableArray *dragItemsArray = [NSMutableArray array];
798 NSEnumerator *enumerator = [dragItems objectEnumerator];
799 AIListObject *listObject;
800
801 while ((listObject = [enumerator nextObject])) {
802 [dragItemsArray addObject:[listObject internalObjectID]];
803 }
804
805 [sender setPropertyList:dragItemsArray forType:@"AIListObjectUniqueIDs"];
806 }
807 }
808}
809
810- (NSDragOperation)tableView:(NSTableView*)tv
811 validateDrop:(id <NSDraggingInfo>)info
812 proposedRow:(int)row
813 proposedDropOperation:(NSTableViewDropOperation)op
814{
815
816 NSDragOperation dragOp = NSDragOperationCopy;
817
818 if ([info draggingSource] == table) {
819 dragOp = NSDragOperationMove;
820 }
821 [tv setDropRow:row dropOperation:NSTableViewDropAbove];
822
823 return dragOp;
824}
825
826- (void)addListObjectToList:(AIListObject *)listObject
827{
828 AIListObject *containedObject;
829 NSEnumerator *enumerator;
830
831 if ([listObject isKindOfClass:[AIListGroup class]]) {
832 enumerator = [[(AIListGroup *)listObject listContacts] objectEnumerator];
833 while ((containedObject = [enumerator nextObject])) {
834 [self addListObjectToList:containedObject];
835 }
836
837 } else if ([listObject isKindOfClass:[AIMetaContact class]]) {
838 enumerator = [[(AIMetaContact *)listObject listContacts] objectEnumerator];
839 while ((containedObject = [enumerator nextObject])) {
840 [self addListObjectToList:containedObject];
841 }
842
843 } else if ([listObject isKindOfClass:[AIListContact class]]) {
844 //if the account for this contact is connected...
845 if ([[(AIListContact *)listObject account] online]) {
846 [self addObject:(AIListContact *)listObject];
847 }
848 }
849}
850
851- (BOOL)tableView:(NSTableView*)tv acceptDrop:(id <NSDraggingInfo>)info row:(int)row dropOperation:(NSTableViewDropOperation)op
852{
853 BOOL accept = NO( BOOL ) 0;
854 if (row < 0)
855 row = 0;
856
857 if ([[[info draggingPasteboard] types] containsObject:@"AIListObjectUniqueIDs"]) {
858 NSArray *dragItemsUniqueIDs = [[info draggingPasteboard] propertyListForType:@"AIListObjectUniqueIDs"];
859 NSString *uniqueUID;
860 NSEnumerator *idEnumerator = [dragItemsUniqueIDs objectEnumerator];
861 while ((uniqueUID = [idEnumerator nextObject]))
862 [self addListObjectToList:[[adium contactController] existingListObjectWithUniqueID:uniqueUID]];
863 accept = YES( BOOL ) 1;
864 }
865
866 return accept;
867}
868
869@end