adium/adium
Clone
Summary
Browse
Changes
Graph
Adding +[NSString randomString] seems to be popular, it appears to be colliding with some plugin I have loaded. Add a prefix here.
adium-1.5.11
2014-12-16, Thijs Alkemade
c4b291694b4a
Adding +[NSString randomString] seems to be popular, it appears to be colliding with some plugin I have loaded. Add a prefix here.
/*
* 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 <Adium/AIStatus.h>
#import <Adium/AIStatusIcons.h>
#import <Adium/AIAccountControllerProtocol.h>
#import <Adium/AIStatusControllerProtocol.h>
#import <Adium/AIHTMLDecoder.h>
#import <AIUtilities/AIAttributedStringAdditions.h>
#import <AIUtilities/AIStringAdditions.h>
@implementation
AIStatus
/*!
* @brief Create an autoreleased AIStatus
*
* @result New autoreleased AIStatus
*/
+
(
AIStatus
*
)
status
{
AIStatus
*
newStatus
=
[[[
self
alloc
]
init
]
autorelease
];
//Configure defaults as necessary
[
newStatus
setAutoReplyIsStatusMessage
:
YES
];
return
newStatus
;
}
/*!
* @brief Crate an AIStatus from a dictionary
*
* @param inDictionary A dictionary of keys to use as the new AIStatus's statusDict
* @result AIStatus from inDictionary
*/
+
(
AIStatus
*
)
statusWithDictionary:
(
NSDictionary
*
)
inDictionary
{
AIStatus
*
status
=
[
self
status
];
[
status
->
statusDict
addEntriesFromDictionary
:
inDictionary
];
return
status
;
}
/*!
* @brief Create an autoreleased AIStatus of a specified type
*
* The new AIStatus will have its statusType and statusName set appropriately.
*
* @result New autoreleased AIStatus
*/
+
(
AIStatus
*
)
statusOfType:
(
AIStatusType
)
inStatusType
{
AIStatus
*
status
=
[
self
status
];
[
status
setStatusType
:
inStatusType
];
[
status
setStatusName
:
[
adium
.
statusController
defaultStatusNameForType
:
inStatusType
]];
if
(
inStatusType
==
AIAwayStatusType
)
{
[
status
setHasAutoReply
:
YES
];
}
return
status
;
}
-
(
void
)
dealloc
{
[
filteredStatusMessage
release
];
[
super
dealloc
];
}
/*!
* @brief Returns an appropriate icon for this state
*
* This method will generate an appropriate status icon based on the state's content.
*
* @param iconType The AIStatusIconType to use
* @result An <tt>NSImage</tt>
*/
-
(
NSImage
*
)
iconOfType:
(
AIStatusIconType
)
iconType
direction:
(
AIIconDirection
)
direction
{
NSString
*
statusName
;
AIStatusType
statusType
;
if
([
self
shouldForceInitialIdleTime
])
{
statusName
=
@"Idle"
;
statusType
=
AIAwayStatusType
;
}
else
{
statusName
=
self
.
statusName
;
statusType
=
self
.
statusType
;
}
return
[
AIStatusIcons
statusIconForStatusName
:
statusName
statusType
:
statusType
iconType
:
iconType
direction
:
direction
];
}
/*!
* @brief The status message for this status
*
* @result An NSAttributedString status message, or nil if no status message or a 0-length status message is set
*/
-
(
NSAttributedString
*
)
statusMessage
{
NSAttributedString
*
statusMessage
;
statusMessage
=
[
statusDict
objectForKey
:
STATUS_STATUS_MESSAGE
];
if
(
!
[
statusMessage
length
])
statusMessage
=
nil
;
return
statusMessage
;
}
/*!
* @brief Return the status message as a string
*/
-
(
NSString
*
)
statusMessageString
{
return
[
self
.
statusMessage
string
];
}
/*!
* @brief Set the status message
*/
-
(
void
)
setStatusMessage:
(
NSAttributedString
*
)
statusMessage
{
if
(
statusMessage
)
{
[
statusDict
setObject
:
statusMessage
forKey
:
STATUS_STATUS_MESSAGE
];
}
else
{
[
statusDict
removeObjectForKey
:
STATUS_STATUS_MESSAGE
];
}
[
filteredStatusMessage
release
];
filteredStatusMessage
=
nil
;
}
/*!
* @brief Set the status message as a string
*
* @param statusMessageString The status message as a string; HTML may be passed if desired
*/
-
(
void
)
setStatusMessageString:
(
NSString
*
)
statusMessageString
{
[
self
setStatusMessage
:
[
AIHTMLDecoder
decodeHTML
:
statusMessageString
]];
}
-
(
void
)
setFilteredStatusMessage:
(
NSString
*
)
inFilteredStatusMessage
{
if
(
!
[
filteredStatusMessage
isEqualToString
:
inFilteredStatusMessage
])
{
[
filteredStatusMessage
release
];
filteredStatusMessage
=
[
inFilteredStatusMessage
retain
];
[[
NSNotificationCenter
defaultCenter
]
postNotificationName
:
@"AIStatusFilteredStatusMessageChanged"
object
:
self
];
}
}
-
(
NSString
*
)
statusMessageTooltipString
{
return
(
filteredStatusMessage
?
filteredStatusMessage
:
[
self
statusMessageString
]);
}
/*!
* @brief The auto reply to send when in this status
*
* @result An NSAttributedString auto reply, or nil if no auto reply should be sent
*/
-
(
NSAttributedString
*
)
autoReply
{
NSAttributedString
*
autoReply
=
nil
;
if
([
self
hasAutoReply
])
{
autoReply
=
([
self
autoReplyIsStatusMessage
]
?
self
.
statusMessage
:
[
statusDict
objectForKey
:
STATUS_AUTO_REPLY_MESSAGE
]);
}
if
(
!
[
autoReply
length
])
autoReply
=
nil
;
return
autoReply
;
}
/*!
* @brief Autoreply as a string
*/
-
(
NSString
*
)
autoReplyString
{
return
[[
self
autoReply
]
string
];
}
/*!
* @brief Set the autoReply
*/
-
(
void
)
setAutoReply:
(
NSAttributedString
*
)
autoReply
{
if
(
autoReply
)
{
[
statusDict
setObject
:
autoReply
forKey
:
STATUS_AUTO_REPLY_MESSAGE
];
}
else
{
[
statusDict
removeObjectForKey
:
STATUS_AUTO_REPLY_MESSAGE
];
}
}
/*!
* @brief Set the autoreply as a string
*
* @param autoReplyString The autoreply as a string; HTML may be passed if desired
*/
-
(
void
)
setAutoReplyString:
(
NSString
*
)
autoReplyString
{
[
self
setAutoReply
:
[
AIHTMLDecoder
decodeHTML
:
autoReplyString
]];
}
/*!
* @brief Does this status state send an autoReeply?
*/
-
(
BOOL
)
hasAutoReply
{
return
[[
statusDict
objectForKey
:
STATUS_HAS_AUTO_REPLY
]
boolValue
];
}
/*!
* @brief Set if this status sends an autoReply
*/
-
(
void
)
setHasAutoReply:
(
BOOL
)
hasAutoReply
{
[
statusDict
setObject
:
[
NSNumber
numberWithBool
:
hasAutoReply
]
forKey
:
STATUS_HAS_AUTO_REPLY
];
}
/*!
* @brief Is the autoReply the same as the status message?
*/
-
(
BOOL
)
autoReplyIsStatusMessage
{
return
[[
statusDict
objectForKey
:
STATUS_AUTO_REPLY_IS_STATUS_MESSAGE
]
boolValue
];
}
/*!
* @brief Set if the autoReply is the same as the status message
*/
-
(
void
)
setAutoReplyIsStatusMessage:
(
BOOL
)
autoReplyIsStatusMessage
{
[
statusDict
setObject
:
[
NSNumber
numberWithBool
:
autoReplyIsStatusMessage
]
forKey
:
STATUS_AUTO_REPLY_IS_STATUS_MESSAGE
];
}
/*!
* @brief Returns an appropriate title
*
* Not all states provide a title. This method will generate an appropriate title based on the states' content.
* If the state has a specified title, it will always be used.
*/
-
(
NSString
*
)
title
{
NSAttributedString
*
statusMessage
,
*
autoReply
;
NSString
*
title
=
nil
;
AIStatusType
statusType
;
NSRange
linebreakRange
;
//Start off using super's implementation, looking for a directly assigned title
title
=
[
super
title
];
/* Now we start falling through looking to generate a title if we don't have one yet */
//If the state has a status message, use it.
if
(
!
title
&&
(
statusMessage
=
self
.
statusMessage
)
&&
([
statusMessage
length
]))
{
title
=
[
statusMessage
string
];
}
//If the state has an autoreply (but no status message), use it.
if
(
!
title
&&
(
autoReply
=
[
self
autoReply
])
&&
([
autoReply
length
]))
{
title
=
[
autoReply
string
];
}
/* If the state is not an available state, or it's an available state with a non-default statusName,
* use the description of the state itself. */
statusType
=
self
.
statusType
;
if
(
!
title
&&
((
self
.
statusType
!=
AIAvailableStatusType
)
||
((
self
.
statusName
!=
nil
)
&&
!
[
self
.
statusName
isEqualToString
:
STATUS_NAME_AVAILABLE
])))
{
title
=
[
adium
.
statusController
descriptionForStateOfStatus
:
self
];
}
//If the state is simply idle, use the string "Idle"
if
(
!
title
&&
[
self
shouldForceInitialIdleTime
])
{
title
=
AILocalizedString
(
@"Idle"
,
nil
);
}
if
(
!
title
&&
(
statusType
==
AIOfflineStatusType
))
{
title
=
[
adium
.
statusController
localizedDescriptionForCoreStatusName
:
STATUS_NAME_OFFLINE
];
}
//If the state is none of the above, use the string "Available"
if
(
!
title
)
title
=
[
adium
.
statusController
localizedDescriptionForCoreStatusName
:
STATUS_NAME_AVAILABLE
];
//Strip newlines and whitespace from the beginning and the end
title
=
[
title
stringByTrimmingCharactersInSet
:
[
NSCharacterSet
whitespaceAndNewlineCharacterSet
]];
//Only use the first line of a multi-line title
linebreakRange
=
[
title
lineRangeForRange
:
NSMakeRange
(
0
,
0
)];
//check to make sure that there actually is a linebreak to account for
// by comparing the linebreak range against the whole string's range.
if
(
!
NSEqualRanges
(
linebreakRange
,
NSMakeRange
(
0
,
[
title
length
]))
)
{
title
=
[
title
substringWithRange
:
linebreakRange
];
}
return
title
;
}
/*!
* @brief The specific status name
*
* This is a name which was added as available by one or more installed AIService objects. Accounts should
* use this name if possible, handle the other Adium default statusName values if not, and then, if all else fails
* use the return of statusType to know the general type of status.
*/
-
(
NSString
*
)
statusName
{
return
[
statusDict
objectForKey
:
STATUS_STATUS_NAME
];
}
/*!
* @brief Set the specific status name
*
* Set the name which will be used by accounts to know which specific state to apply when this status is made active.
* This name is for internal use only and should not be localized.
*/
-
(
void
)
setStatusName:
(
NSString
*
)
statusName
{
if
(
statusName
)
{
[
statusDict
setObject
:
statusName
forKey
:
STATUS_STATUS_NAME
];
}
else
{
[
statusDict
removeObjectForKey
:
STATUS_STATUS_NAME
];
}
}
/*!
* @brief Should this state force an account to be idle?
*
* @result YES if the account will be forced to be idle
*/
-
(
BOOL
)
shouldForceInitialIdleTime
{
return
[[
statusDict
objectForKey
:
STATUS_SHOULD_FORCE_INITIAL_IDLE_TIME
]
boolValue
];
}
/*!
* @brief Set if this state should force an account to be idle?
*
* @param shouldForceInitialIdleTime YES if the account will be forced to be idle
*/
-
(
void
)
setShouldForceInitialIdleTime:
(
BOOL
)
shouldForceInitialIdleTime
{
[
statusDict
setObject
:
[
NSNumber
numberWithBool
:
shouldForceInitialIdleTime
]
forKey
:
STATUS_SHOULD_FORCE_INITIAL_IDLE_TIME
];
}
/*!
* @brief The time the account should be set to have been idle when this state is set
*
* @result Number of seconds idle
*/
-
(
double
)
forcedInitialIdleTime
{
return
[[
statusDict
objectForKey
:
STATUS_FORCED_INITIAL_IDLE_TIME
]
doubleValue
];
}
/*!
* @brief The time the account should be set to have been idle when this state is set
*
* @param forcedInitialIdleTime Number of seconds idle
*/
-
(
void
)
setForcedInitialIdleTime:
(
double
)
forcedInitialIdleTime
{
[
statusDict
setObject
:
[
NSNumber
numberWithDouble
:
forcedInitialIdleTime
]
forKey
:
STATUS_FORCED_INITIAL_IDLE_TIME
];
}
/*!
* @brief Is this status state mutable?
*
* If this method indicates the status state is not mutable, it should not be presented to the user for editing.
* This should be the condition for (and only for) basic saved states built in to Adium.
*
* @result AIStateMutabilityType value
*/
-
(
AIStatusMutabilityType
)
mutabilityType
{
return
[[
statusDict
objectForKey
:
STATUS_MUTABILITY_TYPE
]
intValue
];
}
/*!
* @brief Set the mutability type of this status. The default is AIEditableState
*/
-
(
void
)
setMutabilityType:
(
AIStatusMutabilityType
)
mutabilityType
{
[
statusDict
setObject
:
[
NSNumber
numberWithInt
:
mutabilityType
]
forKey
:
STATUS_MUTABILITY_TYPE
];
}
-
(
BOOL
)
mutesSound
{
return
[[
statusDict
objectForKey
:
STATUS_MUTE_SOUNDS
]
boolValue
];
}
-
(
void
)
setMutesSound:
(
BOOL
)
mutes
{
[
statusDict
setObject
:
[
NSNumber
numberWithBool
:
mutes
]
forKey
:
STATUS_MUTE_SOUNDS
];
}
-
(
BOOL
)
silencesGrowl
{
return
[[
statusDict
objectForKey
:
STATUS_SILENCE_GROWL
]
boolValue
];
}
-
(
void
)
setSilencesGrowl:
(
BOOL
)
mutes
{
[
statusDict
setObject
:
[
NSNumber
numberWithBool
:
mutes
]
forKey
:
STATUS_SILENCE_GROWL
];
}
-
(
void
)
setSpecialStatusType:
(
AISpecialStatusType
)
inSpecialStatusType
{
[
statusDict
setObject
:
[
NSNumber
numberWithInt
:
inSpecialStatusType
]
forKey
:
STATUS_SPECIAL_TYPE
];
}
-
(
AISpecialStatusType
)
specialStatusType
{
return
[[
statusDict
objectForKey
:
STATUS_SPECIAL_TYPE
]
intValue
];
}
#pragma mark Applescript
/**
* @brief Returns the message of this status as an NSTextStorage
*/
-
(
NSTextStorage
*
)
scriptingMessage
{
return
[[[
NSTextStorage
alloc
]
initWithAttributedString
:
self
.
statusMessage
]
autorelease
];
}
-
(
void
)
setScriptingMessage:
(
NSTextStorage
*
)
newMessage
{
NSLog
(
@"setScriptingMessage: %@"
,
newMessage
);
if
([
self
mutabilityType
]
==
AIEditableStatusState
||
[
self
mutabilityType
]
==
AITemporaryEditableStatusState
)
{
if
([
newMessage
isKindOfClass
:
[
NSAttributedString
class
]])
[
self
setStatusMessage
:
newMessage
];
else
if
([
newMessage
isKindOfClass
:
[
NSString
class
]])
[
self
setStatusMessageString
:
(
NSString
*
)
newMessage
];
else
{
[[
NSScriptCommand
currentCommand
]
setScriptErrorNumber
:
errOSACantAssign
];
[[
NSScriptCommand
currentCommand
]
setScriptErrorString
:
@"Status message must be a string or an attributed string."
];
return
;
}
[
adium
.
statusController
savedStatusesChanged
];
AILogWithSignature
(
@"Applying %@ to %@"
,
self
,
[
adium
.
accountController
accountsWithCurrentStatus
:
self
]);
[
adium
.
statusController
applyState
:
self
toAccounts
:
[
adium
.
accountController
accountsWithCurrentStatus
:
self
]];
}
else
{
AIStatus
*
newStatus
=
[[
self
mutableCopy
]
autorelease
];
[
newStatus
setMutabilityType
:
AITemporaryEditableStatusState
];
if
([
newMessage
isKindOfClass
:
[
NSAttributedString
class
]])
[
newStatus
setStatusMessage
:
newMessage
];
else
if
([
newMessage
isKindOfClass
:
[
NSString
class
]])
[
newStatus
setStatusMessageString
:
(
NSString
*
)
newMessage
];
else
{
[[
NSScriptCommand
currentCommand
]
setScriptErrorNumber
:
errOSACantAssign
];
[[
NSScriptCommand
currentCommand
]
setScriptErrorString
:
@"Status message must be a string or an attributed string."
];
return
;
}
[
adium
.
statusController
savedStatusesChanged
];
[
adium
.
statusController
applyState
:
newStatus
toAccounts
:
[
adium
.
accountController
accountsWithCurrentStatus
:
self
]];
}
}
-
(
NSTextStorage
*
)
scriptingAutoreply
{
return
[[[
NSTextStorage
alloc
]
initWithAttributedString
:
[
self
autoReply
]]
autorelease
];
}
-
(
void
)
setScriptingAutoreply:
(
NSTextStorage
*
)
newAutoreply
{
if
([
self
mutabilityType
]
==
AIEditableStatusState
||
[
self
mutabilityType
]
==
AITemporaryEditableStatusState
)
{
if
([
newAutoreply
isKindOfClass
:
[
NSAttributedString
class
]])
[
self
setAutoReply
:
newAutoreply
];
else
if
([
newAutoreply
isKindOfClass
:
[
NSString
class
]])
[
self
setAutoReplyString
:
(
NSString
*
)
newAutoreply
];
else
{
[[
NSScriptCommand
currentCommand
]
setScriptErrorNumber
:
errOSACantAssign
];
[[
NSScriptCommand
currentCommand
]
setScriptErrorString
:
@"Autoreply message must be a string or an attributed string."
];
return
;
}
[
adium
.
statusController
savedStatusesChanged
];
[
adium
.
statusController
applyState
:
self
toAccounts
:
[
adium
.
accountController
accountsWithCurrentStatus
:
self
]];
}
else
{
AIStatus
*
newStatus
=
[[
self
mutableCopy
]
autorelease
];
[
newStatus
setMutabilityType
:
AITemporaryEditableStatusState
];
if
([
newAutoreply
isKindOfClass
:
[
NSAttributedString
class
]])
[
newStatus
setAutoReply
:
newAutoreply
];
else
if
([
newAutoreply
isKindOfClass
:
[
NSString
class
]])
[
newStatus
setAutoReplyString
:
(
NSString
*
)
newAutoreply
];
else
{
[[
NSScriptCommand
currentCommand
]
setScriptErrorNumber
:
errOSACantAssign
];
[[
NSScriptCommand
currentCommand
]
setScriptErrorString
:
@"Autoreply message must be a string or an attributed string."
];
return
;
}
[
adium
.
statusController
savedStatusesChanged
];
[
adium
.
statusController
applyState
:
newStatus
toAccounts
:
[
adium
.
accountController
accountsWithCurrentStatus
:
self
]];
}
}
-
(
void
)
setStatusTypeApplescript:
(
AIStatusTypeApplescript
)
statusTypeApplescript
{
AIStatusType
statusType
;
switch
(
statusTypeApplescript
)
{
case
AIAvailableStatusTypeAS
:
statusType
=
AIAvailableStatusType
;
break
;
case
AIAwayStatusTypeAS
:
statusType
=
AIAwayStatusType
;
break
;
case
AIInvisibleStatusTypeAS
:
statusType
=
AIInvisibleStatusType
;
break
;
case
AIOfflineStatusTypeAS
:
default
:
statusType
=
AIOfflineStatusType
;
break
;
}
if
([
self
mutabilityType
]
==
AIEditableStatusState
||
[
self
mutabilityType
]
==
AITemporaryEditableStatusState
)
{
[
self
setStatusType
:
statusType
];
[
adium
.
statusController
savedStatusesChanged
];
[
adium
.
statusController
applyState
:
self
toAccounts
:
[
adium
.
accountController
accountsWithCurrentStatus
:
self
]];
}
else
{
AIStatus
*
newStatus
=
[[
self
mutableCopy
]
autorelease
];
[
newStatus
setMutabilityType
:
AITemporaryEditableStatusState
];
[
newStatus
setStatusType
:
statusType
];
[
newStatus
setStatusName
:
[
adium
.
statusController
defaultStatusNameForType
:
statusType
]];
[
adium
.
statusController
savedStatusesChanged
];
[
adium
.
statusController
applyState
:
newStatus
toAccounts
:
[
adium
.
accountController
accountsWithCurrentStatus
:
self
]];
}
}
/**
* @brief Returns the title of this status.
*/
-
(
NSString
*
)
scriptingTitle
{
return
[
self
title
];
}
/**
* @brief Sets the title of this status to the given value.
*
* This may copy self, if self is not editable.
*/
-
(
void
)
setScriptingTitle:
(
NSString
*
)
newTitle
{
if
([
self
mutabilityType
]
==
AIEditableStatusState
||
[
self
mutabilityType
]
==
AITemporaryEditableStatusState
)
{
[
self
setTitle
:
newTitle
];
[
adium
.
statusController
savedStatusesChanged
];
[
adium
.
statusController
applyState
:
self
toAccounts
:
[
adium
.
accountController
accountsWithCurrentStatus
:
self
]];
}
else
{
AIStatus
*
newStatus
=
[[
self
mutableCopy
]
autorelease
];
[
newStatus
setMutabilityType
:
AITemporaryEditableStatusState
];
[
newStatus
setTitle
:
newTitle
];
[
adium
.
statusController
savedStatusesChanged
];
[
adium
.
statusController
applyState
:
newStatus
toAccounts
:
[
adium
.
accountController
accountsWithCurrentStatus
:
self
]];
}
}
-
(
BOOL
)
scriptingMutabilityType
{
return
[
self
mutabilityType
]
!=
AITemporaryEditableStatusState
;
}
@end