adium/adium
Clone
Summary
Browse
Changes
Graph
Merge.
adium-1.5.8
1.5.8
2013-10-13, Thijs Alkemade
e0467f507718
Merge.
/*
* 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 "ESAddressBookIntegrationAdvancedPreferences.h"
#import <Adium/AIAddressBookController.h>
#import <Adium/AIContactControllerProtocol.h>
#import <Adium/AILocalizationTextField.h>
#import <AIUtilities/AIDictionaryAdditions.h>
#import <AIUtilities/AIImageAdditions.h>
#import <AIUtilities/AIMenuAdditions.h>
@interface
NSTokenField
(NSTokenFieldAdditions)
-
(
void
)
updateDisplay
;
@end
@implementation
NSTokenField
(NSTokenFieldAdditions)
-
(
void
)
updateDisplay
{
NSRange
selectionRange
=
[[[
self
window
]
fieldEditor
:
YES
forObject
:
self
]
selectedRange
];
// XXX - Reassign objectValue to let NSTokenField know it has changed.
id
objectValue
=
[
self
objectValue
];
[
self
setObjectValue
:
nil
];
[
self
setObjectValue
:
objectValue
];
[[[
self
window
]
fieldEditor
:
YES
forObject
:
self
]
setSelectedRange
:
selectionRange
];
}
@end
@interface
ESAddressBookIntegrationAdvancedPreferences
()
-
(
IBAction
)
changeFormat
:
(
id
)
sender
;
-
(
void
)
sheetDidEnd:
(
NSWindow
*
)
sheet
returnCode:
(
NSInteger
)
returnCode
contextInfo:
(
void
*
)
contextInfo
;
-
(
NSArray
*
)
separateStringIntoTokens:
(
NSString
*
)
string
;
-
(
void
)
changeFormatToFullName:
(
id
)
representedObject
;
-
(
void
)
changeFormatToInitialCharacter:
(
id
)
representedObject
;
@end
/*!
* @class ESAddressBookIntegrationAdvancedPreferences
* @brief Provide advanced preferences for the address book integration
*/
@implementation
ESAddressBookIntegrationAdvancedPreferences
/*!
* @brief Label
*/
-
(
NSString
*
)
label
{
return
AILocalizedString
(
@"Address Book"
,
nil
);
}
/*!
* @brief Nib name
*/
-
(
NSString
*
)
nibName
{
return
@"AddressBookPrefs"
;
}
/*!
* @brief Image for advanced preferences
*/
-
(
NSImage
*
)
image
{
return
[
NSImage
imageNamed
:
@"AddressBook"
forClass
:
[
self
class
]];
}
/*!
* @brief Configure the preference view
*/
-
(
void
)
viewDidLoad
{
[
label_instructions
setLocalizedString
:
AILocalizedString
(
@"Type text and drag name elements to create a custom name format."
,
nil
)];
[
label_names
setLocalizedString
:
AILocalizedString
(
@"Names"
,
nil
)];
[
label_images
setLocalizedString
:
AILocalizedString
(
@"Images"
,
nil
)];
[
label_contacts
setLocalizedString
:
AILocalizedString
(
@"Contacts"
,
nil
)];
[
box_nameElements
setTitle
:
AILocalizedString
(
@"Name elements"
,
"Contains name format tokens"
)];
[
label_firstToken
setLocalizedString
:
AILocalizedString
(
@"First"
,
"First name token"
)];
[
label_middleToken
setLocalizedString
:
AILocalizedString
(
@"Middle"
,
"Middle name token"
)];
[
label_lastToken
setLocalizedString
:
AILocalizedString
(
@"Last"
,
"Last name token"
)];
[
label_nickToken
setLocalizedString
:
AILocalizedString
(
@"Nick"
,
"Nickname token"
)];
NSString
*
displayFormat
=
[
adium
.
preferenceController
preferenceForKey
:
KEY_AB_DISPLAYFORMAT
group
:
PREF_GROUP_ADDRESSBOOK
];
[
tokenField_format
setDelegate
:
self
];
[
tokenField_format
setTokenizingCharacterSet
:
[
NSCharacterSet
characterSetWithCharactersInString
:
@""
]];
[
tokenField_format
setObjectValue
:
[
self
separateStringIntoTokens
:
displayFormat
]];
[
tokenField_firstToken
setDelegate
:
self
];
[
tokenField_firstToken
setStringValue
:
FORMAT_FIRST_FULL
];
[
tokenField_middleToken
setDelegate
:
self
];
[
tokenField_middleToken
setStringValue
:
FORMAT_MIDDLE_FULL
];
[
tokenField_lastToken
setDelegate
:
self
];
[
tokenField_lastToken
setStringValue
:
FORMAT_LAST_FULL
];
[
tokenField_nickToken
setDelegate
:
self
];
[
tokenField_nickToken
setStringValue
:
FORMAT_NICK_FULL
];
[
checkBox_enableImport
setLocalizedString
:
AILocalizedString
(
@"Import my contacts' names from the Address Book"
,
nil
)];
[
checkBox_useFirstName
setLocalizedString
:
AILocalizedString
(
@"Replace Nick with First if not available"
,
nil
)];
[
checkBox_useNickName
setLocalizedString
:
AILocalizedString
(
@"Use Nick exclusively if available"
,
nil
)];
[
checkBox_useABImages
setLocalizedString
:
AILocalizedString
(
@"Use Address Book images as contacts' icons"
,
nil
)];
[
checkBox_preferABImages
setLocalizedString
:
AILocalizedString
(
@"Even if the contact already has a contact icon"
,
nil
)];
[
checkBox_syncAutomatic
setLocalizedString
:
AILocalizedString
(
@"Overwrite Address Book images with contacts' icons"
,
nil
)];
[
checkBox_metaContacts
setLocalizedString
:
AILocalizedString
(
@"Combine contacts listed on a single card"
,
nil
)];
[
checkBox_enableImport
setState
:
[[
adium
.
preferenceController
preferenceForKey
:
KEY_AB_ENABLE_IMPORT
group
:
PREF_GROUP_ADDRESSBOOK
]
boolValue
]];
[
checkBox_useFirstName
setState
:
[[
adium
.
preferenceController
preferenceForKey
:
KEY_AB_USE_FIRSTNAME
group
:
PREF_GROUP_ADDRESSBOOK
]
boolValue
]];
[
checkBox_useNickName
setState
:
[[
adium
.
preferenceController
preferenceForKey
:
KEY_AB_USE_NICKNAME
group
:
PREF_GROUP_ADDRESSBOOK
]
boolValue
]];
[
checkBox_syncAutomatic
setState
:
[[
adium
.
preferenceController
preferenceForKey
:
KEY_AB_IMAGE_SYNC
group
:
PREF_GROUP_ADDRESSBOOK
]
boolValue
]];
[
checkBox_useABImages
setState
:
[[
adium
.
preferenceController
preferenceForKey
:
KEY_AB_USE_IMAGES
group
:
PREF_GROUP_ADDRESSBOOK
]
boolValue
]];
[
checkBox_enableNoteSync
setState
:
[[
adium
.
preferenceController
preferenceForKey
:
KEY_AB_NOTE_SYNC
group
:
PREF_GROUP_ADDRESSBOOK
]
boolValue
]];
[
checkBox_preferABImages
setState
:
[[
adium
.
preferenceController
preferenceForKey
:
KEY_AB_PREFER_ADDRESS_BOOK_IMAGES
group
:
PREF_GROUP_ADDRESSBOOK
]
boolValue
]];
[
checkBox_metaContacts
setState
:
[[
adium
.
preferenceController
preferenceForKey
:
KEY_AB_CREATE_METACONTACTS
group
:
PREF_GROUP_ADDRESSBOOK
]
boolValue
]];
[
self
configureControlDimming
];
}
/*!
* @brief Deallocate
*/
-
(
void
)
dealloc
{
[
super
dealloc
];
}
/*!
* @brief Configure control dimming
*/
-
(
void
)
configureControlDimming
{
BOOL
enableImport
=
[[
adium
.
preferenceController
preferenceForKey
:
KEY_AB_ENABLE_IMPORT
group
:
PREF_GROUP_ADDRESSBOOK
]
boolValue
];
BOOL
useImages
=
[[
adium
.
preferenceController
preferenceForKey
:
KEY_AB_USE_IMAGES
group
:
PREF_GROUP_ADDRESSBOOK
]
boolValue
];
[
label_instructions
setTextColor
:
((
enableImport
)
?
[
NSColor
controlTextColor
]
:
[
NSColor
disabledControlTextColor
])];
//Use Nick Name and the format menu are irrelevent if importing of names is not enabled
[
checkBox_useFirstName
setEnabled
:
enableImport
];
[
checkBox_useNickName
setEnabled
:
enableImport
];
[
tokenField_format
setEnabled
:
enableImport
];
[
tokenField_firstToken
setEnabled
:
enableImport
];
[
tokenField_middleToken
setEnabled
:
enableImport
];
[
tokenField_lastToken
setEnabled
:
enableImport
];
[
tokenField_nickToken
setEnabled
:
enableImport
];
//We will not allow image syncing if AB images are preferred
//so disable the control and uncheck the box to indicate this to the user
//dchoby98: why are image import and export linked?
//[checkBox_syncAutomatic setEnabled:!preferABImages];
//if (preferABImages)
// [checkBox_syncAutomatic setState:NSOffState];
//Disable the image priority checkbox if we aren't using images
[
checkBox_preferABImages
setEnabled
:
useImages
];
}
/*!
* @brief Save changed name format preference
*/
-
(
IBAction
)
changeFormat:
(
id
)
sender
{
[
adium
.
preferenceController
setPreference
:
[[
sender
objectValue
]
componentsJoinedByString
:
@""
]
forKey
:
KEY_AB_DISPLAYFORMAT
group
:
PREF_GROUP_ADDRESSBOOK
];
}
/*!
* @brief Save changed preference
*/
-
(
IBAction
)
changePreference:
(
id
)
sender
{
if
(
sender
==
checkBox_syncAutomatic
)
{
[
adium
.
preferenceController
setPreference
:
[
NSNumber
numberWithBool
:
([
sender
state
]
==
NSOnState
)]
forKey
:
KEY_AB_IMAGE_SYNC
group
:
PREF_GROUP_ADDRESSBOOK
];
}
else
if
(
sender
==
checkBox_useABImages
)
{
[
adium
.
preferenceController
setPreference
:
[
NSNumber
numberWithBool
:
([
sender
state
]
==
NSOnState
)]
forKey
:
KEY_AB_USE_IMAGES
group
:
PREF_GROUP_ADDRESSBOOK
];
}
else
if
(
sender
==
checkBox_useFirstName
)
{
[
adium
.
preferenceController
setPreference
:
[
NSNumber
numberWithBool
:
([
sender
state
]
==
NSOnState
)]
forKey
:
KEY_AB_USE_FIRSTNAME
group
:
PREF_GROUP_ADDRESSBOOK
];
}
else
if
(
sender
==
checkBox_useNickName
)
{
[
adium
.
preferenceController
setPreference
:
[
NSNumber
numberWithBool
:
([
sender
state
]
==
NSOnState
)]
forKey
:
KEY_AB_USE_NICKNAME
group
:
PREF_GROUP_ADDRESSBOOK
];
}
else
if
(
sender
==
checkBox_enableImport
)
{
[
adium
.
preferenceController
setPreference
:
[
NSNumber
numberWithBool
:
([
sender
state
]
==
NSOnState
)]
forKey
:
KEY_AB_ENABLE_IMPORT
group
:
PREF_GROUP_ADDRESSBOOK
];
}
else
if
(
sender
==
checkBox_preferABImages
)
{
[
adium
.
preferenceController
setPreference
:
[
NSNumber
numberWithBool
:
([
sender
state
]
==
NSOnState
)]
forKey
:
KEY_AB_PREFER_ADDRESS_BOOK_IMAGES
group
:
PREF_GROUP_ADDRESSBOOK
];
}
else
if
(
sender
==
checkBox_enableNoteSync
)
{
[
adium
.
preferenceController
setPreference
:
[
NSNumber
numberWithBool
:
([
sender
state
]
==
NSOnState
)]
forKey
:
KEY_AB_NOTE_SYNC
group
:
PREF_GROUP_ADDRESSBOOK
];
}
else
if
(
sender
==
checkBox_metaContacts
)
{
BOOL
shouldCreateMetaContacts
=
([
sender
state
]
==
NSOnState
);
if
(
shouldCreateMetaContacts
)
{
[
adium
.
preferenceController
setPreference
:
[
NSNumber
numberWithBool
:
YES
]
forKey
:
KEY_AB_CREATE_METACONTACTS
group
:
PREF_GROUP_ADDRESSBOOK
];
}
else
{
NSBeginAlertSheet
(
nil
,
AILocalizedString
(
@"Unconsolidate all metacontacts"
,
nil
),
AILocalizedString
(
@"Cancel"
,
nil
),
nil
,
[[
self
view
]
window
],
self
,
@selector
(
sheetDidEnd
:
returnCode
:
contextInfo
:
),
NULL
,
NULL
,
AILocalizedString
(
@"Disabling automatic contact consolidation will also unconsolidate all existing metacontacts, including any created manually. You will need to recreate any manually-created metacontacts if you proceed."
,
nil
));
}
}
[
self
configureControlDimming
];
}
-
(
void
)
sheetDidEnd:
(
NSWindow
*
)
sheet
returnCode:
(
NSInteger
)
returnCode
contextInfo:
(
void
*
)
contextInfo
{
if
(
returnCode
==
NSAlertDefaultReturn
)
{
//If we now shouldn't create metaContacts, clear 'em all... not pretty, but effective.
//Delay to the next run loop to give better UI responsiveness
[
adium
.
contactController
performSelector
:
@selector
(
clearAllMetaContactData
)
withObject
:
nil
afterDelay
:
0
];
[
adium
.
preferenceController
setPreference
:
[
NSNumber
numberWithBool
:
NO
]
forKey
:
KEY_AB_CREATE_METACONTACTS
group
:
PREF_GROUP_ADDRESSBOOK
];
}
else
{
//Put the checkbox back
[
checkBox_metaContacts
setState
:!
[
checkBox_metaContacts
state
]];
}
}
#pragma mark Token Field Delegate
-
(
NSArray
*
)
tokenField:
(
NSTokenField
*
)
tokenField
shouldAddObjects:
(
NSArray
*
)
tokens
atIndex:
(
NSUInteger
)
index
{
NSString
*
tokenStrings
=
[
tokens
componentsJoinedByString
:
@""
];
return
[
self
separateStringIntoTokens
:
tokenStrings
];
}
-
(
BOOL
)
tokenField:
(
NSTokenField
*
)
tokenField
writeRepresentedObjects:
(
NSArray
*
)
objects
toPasteboard:
(
NSPasteboard
*
)
pboard
{
[
pboard
setString
:
[
objects
componentsJoinedByString
:
@""
]
forType
:
NSStringPboardType
];
return
YES
;
}
-
(
NSArray
*
)
tokenField:
(
NSTokenField
*
)
tokenField
readFromPasteboard:
(
NSPasteboard
*
)
pboard
{
return
[
self
separateStringIntoTokens
:
[
pboard
stringForType
:
NSStringPboardType
]];
}
-
(
NSTokenStyle
)
tokenField:
(
NSTokenField
*
)
tokenField
styleForRepresentedObject:
(
id
)
representedObject
{
if
([
representedObject
hasPrefix
:
@"%["
]
&&
[
representedObject
hasSuffix
:
@"]"
])
{
return
NSRoundedTokenStyle
;
}
else
{
return
NSPlainTextTokenStyle
;
}
}
-
(
NSString
*
)
tokenField:
(
NSTokenField
*
)
tokenField
displayStringForRepresentedObject:
(
id
)
representedObject
{
if
([
representedObject
isEqualToString
:
FORMAT_FIRST_FULL
])
{
return
@"Evan"
;
}
else
if
([
representedObject
isEqualToString
:
FORMAT_FIRST_INITIAL
])
{
return
@"E"
;
}
else
if
([
representedObject
isEqualToString
:
FORMAT_MIDDLE_FULL
])
{
return
@"Dreskin"
;
}
else
if
([
representedObject
isEqualToString
:
FORMAT_MIDDLE_INITIAL
])
{
return
@"D"
;
}
else
if
([
representedObject
isEqualToString
:
FORMAT_LAST_FULL
])
{
return
@"Schoenberg"
;
}
else
if
([
representedObject
isEqualToString
:
FORMAT_LAST_INITIAL
])
{
return
@"S"
;
}
else
if
([
representedObject
isEqualToString
:
FORMAT_NICK_FULL
])
{
return
@"TekJew"
;
}
else
if
([
representedObject
isEqualToString
:
FORMAT_NICK_INITIAL
])
{
return
@"T"
;
}
else
{
return
nil
;
}
}
-
(
NSString
*
)
tokenField:
(
NSTokenField
*
)
tokenField
editingStringForRepresentedObject:
(
id
)
representedObject
{
if
([
representedObject
hasPrefix
:
@"%["
]
&&
[
representedObject
hasSuffix
:
@"]"
])
{
return
nil
;
}
else
{
return
representedObject
;
}
}
-
(
id
)
tokenField:
(
NSTokenField
*
)
tokenField
representedObjectForEditingString:
(
NSString
*
)
editingString
{
if
([
editingString
hasPrefix
:
@"%["
]
&&
[
editingString
hasSuffix
:
@"]"
])
{
// Return mutable string as formats should be modifiable
return
[
NSMutableString
stringWithString
:
editingString
];
}
else
{
return
editingString
;
}
}
-
(
BOOL
)
tokenField:
(
NSTokenField
*
)
tokenField
hasMenuForRepresentedObject:
(
id
)
representedObject
{
if
(
tokenField
==
tokenField_format
)
{
// Only tokens in Format should have menus
return
YES
;
}
else
{
return
NO
;
}
}
-
(
NSMenu
*
)
tokenField:
(
NSTokenField
*
)
tokenField
menuForRepresentedObject:
(
id
)
representedObject
{
NSMenu
*
menu
=
[[[
NSMenu
alloc
]
init
]
autorelease
];
if
(
!
representedObject
)
return
nil
;
NSString
*
fullName
=
[
self
tokenField
:
tokenField
displayStringForRepresentedObject
:[
representedObject
stringByReplacingOccurrencesOfString
:
@"INITIAL"
withString
:
@"FULL"
]];
[
menu
addItemWithTitle
:
fullName
target
:
self
action
:
@selector
(
changeFormatToFullName
:
)
keyEquivalent
:
@""
representedObject
:
representedObject
];
NSString
*
initialCharacter
=
[
self
tokenField
:
tokenField
displayStringForRepresentedObject
:[
representedObject
stringByReplacingOccurrencesOfString
:
@"FULL"
withString
:
@"INITIAL"
]];
[
menu
addItemWithTitle
:
initialCharacter
target
:
self
action
:
@selector
(
changeFormatToInitialCharacter
:
)
keyEquivalent
:
@""
representedObject
:
representedObject
];
return
menu
;
}
-
(
void
)
changeFormatToInitialCharacter:
(
id
)
sender
{
[[
sender
representedObject
]
replaceOccurrencesOfString
:
FORMAT_FULL
withString
:
FORMAT_INITIAL
options
:
NSLiteralSearch
range
:
NSMakeRange
(
0
,
[[
sender
representedObject
]
length
])];
[
tokenField_format
updateDisplay
];
[
self
changeFormat
:
tokenField_format
];
}
-
(
void
)
changeFormatToFullName:
(
id
)
sender
{
[[
sender
representedObject
]
replaceOccurrencesOfString
:
FORMAT_INITIAL
withString
:
FORMAT_FULL
options
:
NSLiteralSearch
range
:
NSMakeRange
(
0
,
[[
sender
representedObject
]
length
])];
[
tokenField_format
updateDisplay
];
[
self
changeFormat
:
tokenField_format
];
}
-
(
NSArray
*
)
separateStringIntoTokens:
(
NSString
*
)
string
{
NSMutableArray
*
tokens
=
[
NSMutableArray
array
];
int
i
=
0
;
while
(
i
<
[
string
length
])
{
unsigned
int
start
=
i
;
// Search for end of current token
if
([[
string
substringFromIndex
:
i
]
hasPrefix
:
@"%["
])
{
for
(;
i
<
[
string
length
];
i
++
)
{
if
([[
string
substringFromIndex
:
i
]
hasPrefix
:
@"]"
])
{
i
++
;
break
;
}
}
// Search for start of next token
}
else
{
for
(;
i
<
[
string
length
];
i
++
)
{
if
([[
string
substringFromIndex
:
(
i
+
1
)]
hasPrefix
:
@"%["
])
{
i
++
;
break
;
}
}
}
[
tokens
addObject
:
[[[
string
substringWithRange
:
NSMakeRange
(
start
,
i
-
start
)]
mutableCopy
]
autorelease
]];
}
return
tokens
;
}
@end