adium/adium
Clone
Summary
Browse
Changes
Graph
Updated Sparkle to 1.17.0, to fix a problem when copying broken symlinks.
adium-1.5.10.4
2017-04-23, Thijs Alkemade
5883c460b8cb
Updated Sparkle to 1.17.0, to fix a problem when copying broken symlinks.
/*
* Adium is the legal property of its developers, whose names are listed in the copyright file included
* with this source distribution.
*
* This program is free software; you can redistribute it and/or modify it under the terms of the GNU
* General Public License as published by the Free Software Foundation; either version 2 of the License,
* or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if not,
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#import "RAFBlockEditorWindowController.h"
#import <Adium/AIAccountControllerProtocol.h>
#import <Adium/AIContactControllerProtocol.h>
#import <AIUtilities/AICompletingTextField.h>
#import <AIUtilities/AIPopUpButtonAdditions.h>
#import <AIUtilities/AIMenuAdditions.h>
#import <Adium/AIAccount.h>
#import <Adium/AIListContact.h>
#import <Adium/AIMetaContact.h>
#import <Adium/AIListGroup.h>
#import <Adium/AIService.h>
@interface
RAFBlockEditorWindowController
()
-
(
NSMenu
*
)
privacyOptionsMenu
;
-
(
AIAccount
<
AIAccount_Privacy
>
*
)
selectedAccount
;
-
(
void
)
configureTextField
;
-
(
NSSet
*
)
contactsFromTextField
;
-
(
AIPrivacyOption
)
selectedPrivacyOption
;
-
(
void
)
privacySettingsChangedExternally:
(
NSNotification
*
)
inNotification
;
-
(
void
)
runBlockSheet
;
-
(
void
)
removeSelection
;
@end
@implementation
RAFBlockEditorWindowController
static
RAFBlockEditorWindowController
*
sharedInstance
=
nil
;
+
(
void
)
showWindow
{
if
(
!
sharedInstance
)
{
sharedInstance
=
[[
self
alloc
]
initWithWindowNibName
:
@"BlockEditorWindow"
];
}
[
sharedInstance
showWindow
:
nil
];
[[
sharedInstance
window
]
makeKeyAndOrderFront
:
nil
];
}
-
(
void
)
windowDidLoad
{
[[
self
window
]
setTitle
:
AILocalizedString
(
@"Privacy Settings"
,
nil
)];
[
cancelButton
setLocalizedString
:
AILocalizedString
(
@"Cancel"
,
"Cancel button for Privacy Settings"
)];
[
blockButton
setLocalizedString
:
AILocalizedString
(
@"Add"
,
"Add button for Privacy Settings"
)];
[[
buddyCol
headerCell
]
setTitle
:
AILocalizedString
(
@"Contact"
,
"Title of column containing user IDs of blocked contacts"
)];
[[
accountCol
headerCell
]
setTitle
:
AILocalizedString
(
@"Account"
,
"Title of column containing blocking accounts"
)];
[
accountText
setLocalizedString
:
AILocalizedString
(
@"Account:"
,
nil
)];
{
//Let the min X margin be resizeable while label_account and label_privacyLevel localize in case the window moves
[
stateChooser
setAutoresizingMask
:
(
NSViewMinYMargin
|
NSViewMinXMargin
)];
[
popUp_accounts
setAutoresizingMask
:
(
NSViewMinYMargin
|
NSViewMinXMargin
)];
//Keep label_privacyLevel in place, too, while label_account potentially resizes the window
[
label_privacyLevel
setAutoresizingMask
:
(
NSViewMinYMargin
|
NSViewMinXMargin
)];
[
label_account
setLocalizedString
:
AILocalizedString
(
@"Account:"
,
nil
)];
[
label_privacyLevel
setAutoresizingMask
:
(
NSViewMinYMargin
|
NSViewMaxXMargin
)];
//Account is in place; popUp_accounts can width-resize again
[
popUp_accounts
setAutoresizingMask
:
(
NSViewWidthSizable
|
NSViewMinYMargin
)];
[
label_privacyLevel
setLocalizedString
:
AILocalizedString
(
@"Privacy level:"
,
nil
)];
[
stateChooser
setAutoresizingMask
:
(
NSViewWidthSizable
|
NSViewMinYMargin
)];
}
accountColumnsVisible
=
YES
;
[
accountCol
retain
];
listContents
=
[[
NSMutableArray
alloc
]
init
];
[
stateChooser
setMenu
:
[
self
privacyOptionsMenu
]];
[[
table
tableColumnWithIdentifier
:
@"icon"
]
setDataCell
:
[[[
NSImageCell
alloc
]
init
]
autorelease
]];
accountMenu
=
[[
AIAccountMenu
accountMenuWithDelegate
:
self
submenuType
:
AIAccountNoSubmenu
showTitleVerbs
:
NO
]
retain
];
[
table
registerForDraggedTypes
:
[
NSArray
arrayWithObjects
:
@"AIListObject"
,
@"AIListObjectUniqueIDs"
,
nil
]];
[[
NSNotificationCenter
defaultCenter
]
addObserver
:
self
selector
:
@selector
(
privacySettingsChangedExternally
:
)
name
:
@"AIPrivacySettingsChangedOutsideOfPrivacyWindow"
object
:
nil
];
// Force an update, so the window will resize properly.
[
self
accountMenu
:
accountMenu
didSelectAccount
:
[
self
selectedAccount
]];
[[
AIContactObserverManager
sharedManager
]
registerListObjectObserver
:
self
];
[
super
windowDidLoad
];
}
-
(
void
)
windowWillClose:
(
id
)
sender
{
[
super
windowWillClose
:
sender
];
[[
AIContactObserverManager
sharedManager
]
unregisterListObjectObserver
:
self
];
[[
NSNotificationCenter
defaultCenter
]
removeObserver
:
self
];
[
sharedInstance
release
];
sharedInstance
=
nil
;
}
-
(
NSString
*
)
adiumFrameAutosaveName
{
return
@"PrivacyWindow"
;
}
-
(
void
)
dealloc
{
[
accountCol
release
];
[
accountMenu
release
];
[
listContents
release
];
[
listContentsAllAccounts
release
];
[
super
dealloc
];
}
-
(
NSMutableArray
*
)
listContents
{
return
listContents
;
}
-
(
void
)
setListContents:
(
NSArray
*
)
newList
{
if
(
newList
!=
listContents
)
{
[
listContents
release
];
listContents
=
[
newList
mutableCopy
];
}
}
-
(
IBAction
)
addOrRemoveBlock:
(
id
)
sender
{
NSInteger
selectedSegment
=
[
sender
selectedSegment
];
switch
(
selectedSegment
)
{
case
0
:
[
self
runBlockSheet
];
break
;
case
1
:
[
self
removeSelection
];
break
;
}
}
#pragma mark Adding a contact to the list
-
(
void
)
selectAccountInSheet:
(
AIAccount
*
)
inAccount
{
[
popUp_sheetAccounts
selectItemWithRepresentedObject
:
inAccount
];
[
self
configureTextField
];
NSString
*
userNameLabel
=
[
inAccount
.
service
userNameLabel
];
[
accountText
setAutoresizingMask
:
NSViewMinXMargin
];
[
buddyText
setLocalizedString
:
[(
userNameLabel
?
userNameLabel
:
AILocalizedString
(
@"Contact ID"
,
nil
))
stringByAppendingString
:
AILocalizedString
(
@":"
,
"Colon which will be appended after a label such as 'User Name', before an input field"
)]];
[
accountText
setAutoresizingMask
:
NSViewMaxXMargin
];
}
-
(
void
)
runBlockSheet
{
[
field
setStringValue
:
@""
];
sheetAccountMenu
=
[[
AIAccountMenu
accountMenuWithDelegate
:
self
submenuType
:
AIAccountNoSubmenu
showTitleVerbs
:
NO
]
retain
];
[
self
selectAccountInSheet
:
[[
popUp_sheetAccounts
selectedItem
]
representedObject
]];
[
NSApp
beginSheet
:
sheet
modalForWindow
:[
self
window
]
modalDelegate
:
self
didEndSelector
:
@selector
(
didEndSheet
:
returnCode
:
contextInfo
:
)
contextInfo
:
nil
];
}
-
(
IBAction
)
cancelBlockSheet:
(
id
)
sender
{
[
NSApp
endSheet
:
sheet
];
}
-
(
void
)
addObject:
(
AIListContact
*
)
inContact
{
if
(
inContact
)
{
if
(
!
[
listContents
containsObject
:
inContact
])
{
[
listContents
addObject
:
inContact
];
}
[
inContact
setIsOnPrivacyList
:
YES
updateList
:
YES
privacyType
:
(([
self
selectedPrivacyOption
]
==
AIPrivacyOptionAllowUsers
)
?
AIPrivacyTypePermit
:
AIPrivacyTypeDeny
)];
}
}
-
(
IBAction
)
didBlockSheet:
(
id
)
sender
{
NSSet
*
contactArray
=
[
self
contactsFromTextField
];
//Add the contact immediately
if
(
contactArray
&&
[
contactArray
count
])
{
AIListContact
*
contact
;
for
(
contact
in
contactArray
)
{
[
self
addObject
:
contact
];
}
[
table
reloadData
];
}
[
NSApp
endSheet
:
sheet
];
}
-
(
void
)
didEndSheet:
(
NSWindow
*
)
theSheet
returnCode:
(
NSInteger
)
returnCode
contextInfo:
(
void
*
)
contextInfo
{
[
sheetAccountMenu
release
];
sheetAccountMenu
=
nil
;
[
theSheet
orderOut
:
self
];
}
/*!
* @brief Get a set of all contacts which are represented by the currently selected account and UID field
*
* @result A set of AIListContact objects
*/
-
(
NSSet
*
)
contactsFromTextField
{
AIListContact
*
contact
=
nil
;
NSString
*
UID
=
nil
;
AIAccount
*
account
=
[[
popUp_sheetAccounts
selectedItem
]
representedObject
];;
NSArray
*
accountArray
;
NSMutableSet
*
contactsSet
=
[
NSMutableSet
set
];
NSEnumerator
*
enumerator
;
id
impliedValue
=
[
field
impliedValue
];
if
(
account
)
{
accountArray
=
[
NSArray
arrayWithObject
:
account
];
}
else
{
//All accounts
NSMutableArray
*
tempArray
=
[
NSMutableArray
array
];
NSMenuItem
*
menuItem
;
enumerator
=
[[[
popUp_sheetAccounts
menu
]
itemArray
]
objectEnumerator
];
while
((
menuItem
=
[
enumerator
nextObject
]))
{
AIAccount
*
anAccount
;
if
((
anAccount
=
[
menuItem
representedObject
]))
{
[
tempArray
addObject
:
anAccount
];
}
}
accountArray
=
tempArray
;
}
for
(
account
in
accountArray
)
{
if
([
impliedValue
isKindOfClass
:
[
AIMetaContact
class
]])
{
AIListContact
*
containedContact
;
NSEnumerator
*
contactEnumerator
=
[[(
AIMetaContact
*
)
impliedValue
listContactsIncludingOfflineAccounts
]
objectEnumerator
];
while
((
containedContact
=
[
contactEnumerator
nextObject
]))
{
/* For each contact contained my the metacontact, check if its service class matches the current account's.
* If it does, add that contact to our list, using the contactController to get an AIListContact specific for the account.
*/
if
([
containedContact
.
service
.
serviceClass
isEqualToString
:
account
.
service
.
serviceClass
])
{
if
((
contact
=
[
adium
.
contactController
contactWithService
:
account
.
service
account
:
account
UID
:
containedContact
.
UID
]))
{
[
contactsSet
addObject
:
contact
];
}
}
}
}
else
{
if
([
impliedValue
isKindOfClass
:
[
AIListContact
class
]])
{
UID
=
[(
AIListContact
*
)
impliedValue
UID
];
}
else
if
([
impliedValue
isKindOfClass
:
[
NSString
class
]])
{
UID
=
[
account
.
service
normalizeUID
:
impliedValue
removeIgnoredCharacters
:
YES
];
}
if
(
UID
)
{
//Get a contact with this UID on the current account
if
((
contact
=
[
adium
.
contactController
contactWithService
:
account
.
service
account
:
account
UID
:
UID
]))
{
[
contactsSet
addObject
:
contact
];
}
}
}
}
return
contactsSet
;
}
-
(
void
)
configureTextField
{
AIAccount
*
account
=
[[
popUp_sheetAccounts
selectedItem
]
representedObject
];
NSEnumerator
*
enumerator
;
AIListContact
*
contact
;
//Clear the completing strings
[
field
setCompletingStrings
:
nil
];
//Configure the auto-complete view to autocomplete for contacts matching the selected account's service
enumerator
=
[
adium
.
contactController
.
allContacts
objectEnumerator
];
while
((
contact
=
[
enumerator
nextObject
]))
{
if
(
!
account
||
contact
.
service
==
account
.
service
)
{
NSString
*
UID
=
contact
.
UID
;
[
field
addCompletionString
:
contact
.
formattedUID
withImpliedCompletion
:
UID
];
[
field
addCompletionString
:
contact
.
displayName
withImpliedCompletion
:
UID
];
[
field
addCompletionString
:
UID
];
}
}
}
#pragma mark Removing a contact from the list
-
(
void
)
removeSelection
{
NSIndexSet
*
selectedItems
=
[
table
selectedRowIndexes
];
// If there's anything selected..
if
([
selectedItems
count
])
{
AIListContact
*
contact
;
// Iterate through the selected rows (backwards)
for
(
NSInteger
selection
=
[
selectedItems
lastIndex
];
selection
!=
NSNotFound
;
selection
=
[
selectedItems
indexLessThanIndex
:
selection
])
{
contact
=
[
listContents
objectAtIndex
:
selection
];
// Remove from the serverside list
[
contact
setIsOnPrivacyList
:
NO
updateList
:
YES
privacyType
:
(([
self
selectedPrivacyOption
]
==
AIPrivacyOptionAllowUsers
)
?
AIPrivacyTypePermit
:
AIPrivacyTypeDeny
)];
[
listContents
removeObject
:
contact
];
}
[
table
reloadData
];
[
table
deselectAll
:
nil
];
}
}
-
(
void
)
tableViewDeleteSelectedRows:
(
NSTableView
*
)
tableView
{
[
self
removeSelection
];
}
-
(
void
)
setAccountColumnsVisible:
(
BOOL
)
visible
{
if
(
accountColumnsVisible
!=
visible
)
{
if
(
visible
)
{
[
table
addTableColumn
:
accountCol
];
}
else
{
[
table
removeTableColumn
:
accountCol
];
}
[
table
sizeToFit
];
accountColumnsVisible
=
visible
;
}
}
#pragma mark Privacy options menu
-
(
NSMenu
*
)
privacyOptionsMenu
{
//build the menu of states
NSMenu
*
stateMenu
=
[[
NSMenu
alloc
]
init
];
NSMenuItem
*
menuItem
;
menuItem
=
[[
NSMenuItem
alloc
]
initWithTitle
:
AILocalizedString
(
@"Allow anyone"
,
nil
)
action
:
NULL
keyEquivalent
:
@""
];
[
menuItem
setTag
:
AIPrivacyOptionAllowAll
];
[
stateMenu
addItem
:
menuItem
];
[
menuItem
release
];
menuItem
=
[[
NSMenuItem
alloc
]
initWithTitle
:
AILocalizedString
(
@"Allow only contacts on my contact list"
,
nil
)
action
:
NULL
keyEquivalent
:
@""
];
[
menuItem
setTag
:
AIPrivacyOptionAllowContactList
];
[
stateMenu
addItem
:
menuItem
];
[
menuItem
release
];
menuItem
=
[[
NSMenuItem
alloc
]
initWithTitle
:
AILocalizedString
(
@"Allow only certain contacts"
,
nil
)
action
:
NULL
keyEquivalent
:
@""
];
[
menuItem
setTag
:
AIPrivacyOptionAllowUsers
];
[
stateMenu
addItem
:
menuItem
];
[
menuItem
release
];
menuItem
=
[[
NSMenuItem
alloc
]
initWithTitle
:
AILocalizedString
(
@"Block certain contacts"
,
nil
)
action
:
NULL
keyEquivalent
:
@""
];
[
menuItem
setTag
:
AIPrivacyOptionDenyUsers
];
[
stateMenu
addItem
:
menuItem
];
[
menuItem
release
];
/*
tmpItem = [[NSMenuItem alloc] initWithTitle:AILocalizedString(@"Custom settings for each account", nil) action:NULL keyEquivalent:@""];
[tmpItem setRepresentedObject:[NSNumber numberWithInt:AIPrivacyOptionCustom]];
[stateMenu addItem:[tmpItem autorelease]];
*/
return
[
stateMenu
autorelease
];
}
-
(
AIPrivacyOption
)
selectedPrivacyOption
{
return
(
AIPrivacyOption
)[[
stateChooser
selectedItem
]
tag
];
}
/*!
* @brief Set a privacy option and update our view for it
*
* @param sender If nil, we update our display without attempting to change anything on our account
*/
-
(
IBAction
)
setPrivacyOption:
(
id
)
sender
{
AIAccount
<
AIAccount_Privacy
>
*
account
=
[
self
selectedAccount
];
AIPrivacyOption
privacyOption
=
[
self
selectedPrivacyOption
];
//First, let's get the right tab view selected
switch
(
privacyOption
)
{
case
AIPrivacyOptionAllowAll
:
case
AIPrivacyOptionAllowContactList
:
case
AIPrivacyOptionCustom
:
if
(
!
[[[
tabView_contactList
selectedTabViewItem
]
identifier
]
isEqualToString
:
@"empty"
])
{
[
tabView_contactList
selectTabViewItemWithIdentifier
:
@"empty"
];
[
tabView_contactList
setHidden
:
YES
];
NSRect
frame
=
[[
self
window
]
frame
];
CGFloat
tabViewHeight
=
[
tabView_contactList
frame
].
size
.
height
;
frame
.
size
.
height
-=
tabViewHeight
;
frame
.
origin
.
y
+=
tabViewHeight
;
//Don't resize vertically now...
[
tabView_contactList
setAutoresizingMask
:
NSViewWidthSizable
];
[[
self
window
]
setMinSize
:
NSMakeSize
(
250
,
frame
.
size
.
height
)];
[[
self
window
]
setMaxSize
:
NSMakeSize
(
CGFLOAT_MAX
,
frame
.
size
.
height
)];
AILog
(
@"Because of privacy option %i, resizing from %@ to %@"
,
privacyOption
,
NSStringFromRect
([[
self
window
]
frame
]),
NSStringFromRect
(
frame
));
[[
self
window
]
setFrame
:
frame
display
:
YES
animate
:
YES
];
}
break
;
case
AIPrivacyOptionAllowUsers
:
case
AIPrivacyOptionDenyUsers
:
if
(
!
[[[
tabView_contactList
selectedTabViewItem
]
identifier
]
isEqualToString
:
@"list"
])
{
[
tabView_contactList
selectTabViewItemWithIdentifier
:
@"list"
];
NSRect
frame
=
[[
self
window
]
frame
];
CGFloat
tabViewHeight
=
[
tabView_contactList
frame
].
size
.
height
;
frame
.
size
.
height
+=
tabViewHeight
;
frame
.
origin
.
y
-=
tabViewHeight
;
[[
self
window
]
setMinSize
:
NSMakeSize
(
250
,
320
)];
[[
self
window
]
setMaxSize
:
NSMakeSize
(
CGFLOAT_MAX
,
CGFLOAT_MAX
)];
//Set frame after fixing our min/max size so the resize won't fail
AILog
(
@"Because of privacy option %i, resizing from %@ to %@"
,
privacyOption
,
NSStringFromRect
([[
self
window
]
frame
]),
NSStringFromRect
(
frame
));
[[
self
window
]
setFrame
:
frame
display
:
YES
animate
:
YES
];
[
tabView_contactList
setHidden
:
NO
];
//Allow resizing vertically again
[
tabView_contactList
setAutoresizingMask
:
(
NSViewWidthSizable
|
NSViewHeightSizable
)];
}
break
;
case
AIPrivacyOptionDenyAll
:
case
AIPrivacyOptionUnknown
:
NSLog
(
@"We should never see these..."
);
break
;
}
if
(
sender
)
{
if
(
account
)
{
[
account
setPrivacyOptions
:
privacyOption
];
}
else
{
NSEnumerator
*
enumerator
=
[[[
popUp_accounts
menu
]
itemArray
]
objectEnumerator
];
NSMenuItem
*
menuItem
;
AIAccount
<
AIAccount_Privacy
>
*
representedAccount
;
while
((
menuItem
=
[
enumerator
nextObject
]))
{
if
((
representedAccount
=
[
menuItem
representedObject
]))
{
[
representedAccount
setPrivacyOptions
:
privacyOption
];
}
}
}
}
//Now make our listContents array match the serverside arrays for the selected account(s)
[
listContents
removeAllObjects
];
if
((
privacyOption
==
AIPrivacyOptionAllowUsers
)
||
(
privacyOption
==
AIPrivacyOptionDenyUsers
))
{
if
(
account
)
{
[
listContents
addObjectsFromArray
:
[
account
listObjectsOnPrivacyList
:
((
privacyOption
==
AIPrivacyOptionAllowUsers
)
?
AIPrivacyTypePermit
:
AIPrivacyTypeDeny
)]];
}
else
{
NSEnumerator
*
enumerator
=
[[[
popUp_accounts
menu
]
itemArray
]
objectEnumerator
];
NSMenuItem
*
menuItem
;
AIAccount
<
AIAccount_Privacy
>
*
representedAccount
;
while
((
menuItem
=
[
enumerator
nextObject
]))
{
if
((
representedAccount
=
[
menuItem
representedObject
]))
{
[
listContents
addObjectsFromArray
:
[
representedAccount
listObjectsOnPrivacyList
:
((
privacyOption
==
AIPrivacyOptionAllowUsers
)
?
AIPrivacyTypePermit
:
AIPrivacyTypeDeny
)]];
}
}
}
}
[
table
reloadData
];
}
-
(
void
)
selectPrivacyOption:
(
AIPrivacyOption
)
privacyOption
{
if
(
privacyOption
==
AIPrivacyOptionCustom
)
{
if
(
!
[
stateChooser
selectItemWithTag
:
privacyOption
])
{
NSMenuItem
*
menuItem
=
[[
NSMenuItem
alloc
]
initWithTitle
:
AILocalizedString
(
@"(Multiple privacy levels are active)"
,
nil
)
action
:
NULL
keyEquivalent
:
@""
];
[
menuItem
setTag
:
AIPrivacyOptionCustom
];
[[
stateChooser
menu
]
addItem
:
menuItem
];
[
menuItem
release
];
[
stateChooser
selectItemWithTag
:
privacyOption
];
}
}
else
{
//Not on custom; make sure custom isn't still in the menu
NSInteger
customItemIndex
=
[
stateChooser
indexOfItemWithTag
:
AIPrivacyOptionCustom
];
if
(
customItemIndex
!=
-1
)
{
[[
stateChooser
menu
]
removeItemAtIndex
:
customItemIndex
];
}
}
//Now update our view for this privacy option
[
self
setPrivacyOption
:
nil
];
}
#pragma mark Account menu
/*!
* @brief Return the currently selected account, or nil if the 'All' item is selected
*/
-
(
AIAccount
<
AIAccount_Privacy
>
*
)
selectedAccount
{
return
[[
popUp_accounts
selectedItem
]
representedObject
];
}
/*!
* @brief Action called when the account selection changes
*
* Update our view and the privacy option menu to be appropriate for the newly selected account.
* This may be called with a sender of nil by code elsewhere to force an update
*/
-
(
void
)
accountMenu:
(
AIAccountMenu
*
)
inAccountMenu
didSelectAccount:
(
AIAccount
*
)
inAccount
{
if
(
inAccountMenu
==
accountMenu
)
{
AIAccount
<
AIAccount_Privacy
>
*
account
=
[
self
selectedAccount
];
if
(
account
)
{
//Selected an account
AIPrivacyOption
privacyOption
=
[
account
privacyOptions
];
//Don't need the account column when we're showing for just one account
[
self
setAccountColumnsVisible
:
NO
];
[
self
selectPrivacyOption
:
privacyOption
];
}
else
{
//Selected 'All'. We need to determine what privacy option to display for the set of all accounts.
AIPrivacyOption
currentState
=
AIPrivacyOptionUnknown
;
NSEnumerator
*
enumerator
=
[[[
popUp_accounts
menu
]
itemArray
]
objectEnumerator
];
NSMenuItem
*
menuItem
;
while
((
menuItem
=
[
enumerator
nextObject
]))
{
if
((
account
=
[
menuItem
representedObject
]))
{
AIPrivacyOption
accountState
=
[
account
privacyOptions
];
if
(
currentState
==
AIPrivacyOptionUnknown
)
{
//We don't know the state of an account yet
currentState
=
accountState
;
}
else
if
(
accountState
!=
currentState
)
{
currentState
=
AIPrivacyOptionCustom
;
}
}
}
[
self
setAccountColumnsVisible
:
YES
];
[
self
selectPrivacyOption
:
currentState
];
}
}
else
if
(
inAccountMenu
==
sheetAccountMenu
)
{
//Update our sheet for the current account
[
self
selectAccountInSheet
:
inAccount
];
}
}
/*!
* @brief The 'All' menu item for accounts was selected
*
* We simulate an AIAccountMenu delegate call, since the All item was added by RAFBLockEditorWindowController.
*/
-
(
IBAction
)
selectedAllAccountItem:
(
id
)
sender
{
AIAccountMenu
*
relevantAccountMenu
=
(([
sender
menu
]
==
[
popUp_accounts
menu
])
?
accountMenu
:
sheetAccountMenu
);
[
self
accountMenu
:
relevantAccountMenu
didSelectAccount
:
nil
];
}
/*!
* @brief Select an account in our account menu, then update everything else to be appropriate for it
*/
-
(
void
)
selectAccount:
(
AIAccount
*
)
inAccount
{
[
popUp_accounts
selectItemWithRepresentedObject
:
inAccount
];
[
self
accountMenu
:
accountMenu
didSelectAccount
:
inAccount
];
}
/*!
* @brief Add account menu items to our location
*
* Implemented as required by the AccountMenuPlugin protocol.
*
* @param menuItemArray An <tt>NSArray</tt> of <tt>NSMenuItem</tt> objects to be added to the menu
*/
-
(
void
)
accountMenu:
(
AIAccountMenu
*
)
inAccountMenu
didRebuildMenuItems:
(
NSArray
*
)
menuItems
{
AIAccount
*
previouslySelectedAccount
=
nil
;
NSMenuItem
*
menuItem
;
NSMenu
*
menu
=
[[
NSMenu
alloc
]
init
];
/*
* accountMenu isn't set the first time we get here as the accountMenu is created. Similarly, sheetAccountMenu isn't created its first time.
* This code makes the (true) assumption that accountMenu is _always_ created before sheetAccountMenu.
*/
BOOL
isPrimaryAccountMenu
=
(
!
accountMenu
||
(
inAccountMenu
==
accountMenu
));
if
(
isPrimaryAccountMenu
)
{
if
([
popUp_accounts
menu
])
{
previouslySelectedAccount
=
[[
popUp_accounts
selectedItem
]
representedObject
];
}
}
else
if
(
inAccountMenu
==
sheetAccountMenu
)
{
if
([
popUp_sheetAccounts
menu
])
{
previouslySelectedAccount
=
[[
popUp_sheetAccounts
selectedItem
]
representedObject
];
}
}
/*
* As we enumerate, we:
* 1) Determine what state the accounts within the menu are in
* 2) Add the menu items to our menu
*/
for
(
menuItem
in
menuItems
)
{
[
menu
addItem
:
menuItem
];
}
if
(
isPrimaryAccountMenu
)
{
[
popUp_accounts
setMenu
:
menu
];
/* Restore the previous account selection if there was one.
* Whether there was one or not, this will cause the rest of our view update to match the new/current selection
*/
[
self
selectAccount
:
previouslySelectedAccount
];
}
else
{
[
popUp_sheetAccounts
setMenu
:
menu
];
[
self
selectAccountInSheet
:
previouslySelectedAccount
];
}
[
menu
release
];
}
//Add the All menu item first if we have more than one account listed
-
(
NSMenuItem
*
)
accountMenuSpecialMenuItem:
(
AIAccountMenu
*
)
inAccountMenu
{
NSMenuItem
*
allItem
=
nil
;
int
numberOfOnlineAccounts
=
0
;
for
(
AIAccount
*
account
in
adium
.
accountController
.
accounts
)
{
if
([
self
accountMenu
:
inAccountMenu
shouldIncludeAccount
:
account
])
{
numberOfOnlineAccounts
+=
1
;
if
(
numberOfOnlineAccounts
>
1
)
{
allItem
=
[[[
NSMenuItem
alloc
]
initWithTitle
:
AILocalizedString
(
@"All"
,
nil
)
target
:
self
action
:
@selector
(
selectedAllAccountItem
:
)
keyEquivalent
:
@""
]
autorelease
];
break
;
}
}
}
return
allItem
;
}
-
(
BOOL
)
accountMenu:
(
AIAccountMenu
*
)
inAccountMenu
shouldIncludeAccount:
(
AIAccount
*
)
inAccount
{
BOOL
isPrimaryAccountMenu
=
(
!
accountMenu
||
(
inAccountMenu
==
accountMenu
));
if
(
isPrimaryAccountMenu
)
{
return
(
inAccount
.
online
&&
[
inAccount
conformsToProtocol
:
@
protocol
(
AIAccount_Privacy
)]);
}
else
{
AIAccount
*
selectedPrimaryAccount
=
self
.
selectedAccount
;
if
(
selectedPrimaryAccount
)
{
//An account is selected in the main window; only incldue that account in our sheet
return
(
inAccount
==
selectedPrimaryAccount
);
}
else
{
//'All' is selected in the main window; include all accounts which are online and support privacy
return
(
inAccount
.
online
&&
[
inAccount
conformsToProtocol
:
@
protocol
(
AIAccount_Privacy
)]);
}
}
}
-
(
void
)
privacySettingsChangedExternally:
(
NSNotification
*
)
inNotification
{
[
self
accountMenu
:
accountMenu
didSelectAccount
:
[
self
selectedAccount
]];
}
-
(
NSSet
*
)
updateListObject:
(
AIListObject
*
)
inObject
keys:
(
NSSet
*
)
inModifiedKeys
silent:
(
BOOL
)
silent
{
if
([
inModifiedKeys
containsObject
:
KEY_IS_BLOCKED
])
{
[
self
privacySettingsChangedExternally
:
nil
];
}
return
nil
;
}
#pragma mark Table view
-
(
NSInteger
)
numberOfRowsInTableView:
(
NSTableView
*
)
aTableView
{
return
[
listContents
count
];
}
-
(
id
)
tableView:
(
NSTableView
*
)
aTableView
objectValueForTableColumn:
(
NSTableColumn
*
)
aTableColumn
row:
(
NSInteger
)
rowIndex
{
NSString
*
identifier
=
[
aTableColumn
identifier
];
AIListContact
*
contact
=
[
listContents
objectAtIndex
:
rowIndex
];
if
([
identifier
isEqualToString
:
@"icon"
])
{
return
[
contact
menuIcon
];
}
else
if
([
identifier
isEqualToString
:
@"contact"
])
{
return
contact
.
formattedUID
;
}
else
if
([
identifier
isEqualToString
:
@"account"
])
{
return
contact
.
account
.
formattedUID
;
}
return
nil
;
}
-
(
BOOL
)
writeListObjects:
(
NSArray
*
)
inArray
toPasteboard:
(
NSPasteboard
*
)
pboard
{
[
pboard
declareTypes
:
[
NSArray
arrayWithObjects
:
@"AIListObject"
,
@"AIListObjectUniqueIDs"
,
nil
]
owner
:
self
];
[
pboard
setString
:
@"Private"
forType
:
@"AIListObject"
];
if
(
dragItems
!=
inArray
)
{
[
dragItems
release
];
dragItems
=
[
inArray
retain
];
}
return
YES
;
}
-
(
BOOL
)
tableView:
(
NSTableView
*
)
tv
writeRows:
(
NSArray
*
)
rows
toPasteboard:
(
NSPasteboard
*
)
pboard
{
NSMutableArray
*
itemArray
=
[
NSMutableArray
array
];
NSNumber
*
rowNumber
;
for
(
rowNumber
in
rows
)
{
[
itemArray
addObject
:
[
listContents
objectAtIndex
:
[
rowNumber
integerValue
]]];
}
return
[
self
writeListObjects
:
itemArray
toPasteboard
:
pboard
];
}
-
(
BOOL
)
tableView:
(
NSTableView
*
)
aTableView
writeRowsWithIndexes:
(
NSIndexSet
*
)
rowIndexes
toPasteboard:
(
NSPasteboard
*
)
pboard
{
NSMutableArray
*
itemArray
=
[
NSMutableArray
array
];
id
item
;
NSUInteger
bufSize
=
[
rowIndexes
count
];
NSUInteger
*
buf
=
malloc
(
bufSize
*
sizeof
(
NSUInteger
));
NSUInteger
i
;
NSRange
range
=
NSMakeRange
([
rowIndexes
firstIndex
],
([
rowIndexes
lastIndex
]
-
[
rowIndexes
firstIndex
])
+
1
);
[
rowIndexes
getIndexes
:
buf
maxCount
:
bufSize
inIndexRange
:&
range
];
for
(
i
=
0
;
i
!=
bufSize
;
i
++
)
{
if
((
item
=
[
listContents
objectAtIndex
:
buf
[
i
]]))
{
[
itemArray
addObject
:
item
];
}
}
free
(
buf
);
return
[
self
writeListObjects
:
itemArray
toPasteboard
:
pboard
];
}
-
(
void
)
pasteboard:
(
NSPasteboard
*
)
sender
provideDataForType:
(
NSString
*
)
type
{
//Provide an array of internalObjectIDs which can be used to reference all the dragged contacts
if
([
type
isEqualToString
:
@"AIListObjectUniqueIDs"
])
{
if
(
dragItems
)
{
NSMutableArray
*
dragItemsArray
=
[
NSMutableArray
array
];
AIListObject
*
listObject
;
for
(
listObject
in
dragItems
)
{
[
dragItemsArray
addObject
:
listObject
.
internalObjectID
];
}
[
sender
setPropertyList
:
dragItemsArray
forType
:
@"AIListObjectUniqueIDs"
];
}
}
}
-
(
NSDragOperation
)
tableView:
(
NSTableView
*
)
tv
validateDrop
:(
id
<
NSDraggingInfo
>
)
info
proposedRow
:(
NSInteger
)
row
proposedDropOperation
:(
NSTableViewDropOperation
)
op
{
NSDragOperation
dragOp
=
NSDragOperationCopy
;
if
([
info
draggingSource
]
==
table
)
{
dragOp
=
NSDragOperationMove
;
}
[
tv
setDropRow
:
row
dropOperation
:
NSTableViewDropAbove
];
return
dragOp
;
}
-
(
void
)
addListObjectToList:
(
AIListObject
*
)
listObject
{
AIListObject
*
containedObject
;
NSEnumerator
*
enumerator
;
if
([
listObject
isKindOfClass
:
[
AIListGroup
class
]])
{
enumerator
=
[[(
AIListGroup
*
)
listObject
uniqueContainedObjects
]
objectEnumerator
];
while
((
containedObject
=
[
enumerator
nextObject
]))
{
[
self
addListObjectToList
:
containedObject
];
}
}
else
if
([
listObject
isKindOfClass
:
[
AIMetaContact
class
]])
{
enumerator
=
[[(
AIMetaContact
*
)
listObject
uniqueContainedObjects
]
objectEnumerator
];
while
((
containedObject
=
[
enumerator
nextObject
]))
{
[
self
addListObjectToList
:
containedObject
];
}
}
else
if
([
listObject
isKindOfClass
:
[
AIListContact
class
]])
{
//if the account for this contact is connected...
if
([(
AIListContact
*
)
listObject
account
].
online
)
{
[
self
addObject
:
(
AIListContact
*
)
listObject
];
}
}
}
-
(
BOOL
)
tableView:
(
NSTableView
*
)
tv
acceptDrop:
(
id
<
NSDraggingInfo
>
)
info
row:
(
NSInteger
)
row
dropOperation:
(
NSTableViewDropOperation
)
op
{
BOOL
accept
=
NO
;
if
([
info
.
draggingPasteboard
.
types
containsObject
:
@"AIListObjectUniqueIDs"
])
{
for
(
NSString
*
uniqueUID
in
[
info
.
draggingPasteboard
propertyListForType
:
@"AIListObjectUniqueIDs"
])
[
self
addListObjectToList
:
[
adium
.
contactController
existingListObjectWithUniqueID
:
uniqueUID
]];
accept
=
YES
;
}
return
accept
;
}
@end