2 * Adium is the legal property of its developers, whose names are listed in the copyright file included
3 * with this source distribution.
5 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
6 * General Public License as published by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
10 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
11 * Public License for more details.
13 * You should have received a copy of the GNU General Public License along with this program; if not,
14 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 #import "AIContactController.h"
18 #import "AIContentController.h"
19 #import "AIExtendedStatusPlugin.h"
20 #import "AIPreferenceController.h"
21 #import <AIUtilities/AIMutableOwnerArray.h>
22 #import <AIUtilities/AIAttributedStringAdditions.h>
23 #import <Adium/AIAbstractListController.h>
24 #import <Adium/AIListObject.h>
26 #define STATUS_MAX_LENGTH 100
28 @interface AIExtendedStatusPlugin (PRIVATE)
29 - (void)preferencesChanged:(NSNotification *)notification;
33 * @class AIExtendedStatusPlugin
34 * @brief Manage the 'extended status' shown in the contact list
36 * If the contact list layout calls for displaying a status message or idle time (or both), this component manages
37 * generating the appropriate string, storing it in the @"ExtendedStatus" status object, and updating it as necessary.
39 @implementation AIExtendedStatusPlugin
46 [[adium preferenceController] registerPreferenceObserver:self forGroup:PREF_GROUP_LIST_LAYOUT];
48 whitespaceAndNewlineCharacterSet = [[NSCharacterSet whitespaceAndNewlineCharacterSet] retain];
54 - (void)uninstallPlugin
56 [[adium preferenceController] unregisterPreferenceObserver:self];
57 [[adium contactController] unregisterListObjectObserver:self];
61 * @brief Preferences changes
63 * PREF_GROUP_LIST_LAYOUT changed; update our list objects if needed.
65 - (void)preferencesChangedForGroup:(NSString *)group key:(NSString *)key
66 object:(AIListObject *)object preferenceDict:(NSDictionary *)prefDict firstTime:(BOOL)firstTime
68 BOOL oldShowStatus = showStatus;
69 BOOL oldShowIdle = showIdle;
71 EXTENDED_STATUS_STYLE statusStyle = [[prefDict objectForKey:KEY_LIST_LAYOUT_EXTENDED_STATUS_STYLE] intValue];
72 showStatus = ((statusStyle == STATUS_ONLY) || (statusStyle == IDLE_AND_STATUS));
73 showIdle = ((statusStyle == IDLE_ONLY) || (statusStyle == IDLE_AND_STATUS));
76 [[adium contactController] registerListObjectObserver:self];
78 if((oldShowStatus != showStatus) || (oldShowIdle != showIdle)){
79 [[adium contactController] updateAllListObjectsForObserver:self];
85 * @brief Update list object's extended status messages
87 - (NSSet *)updateListObject:(AIListObject *)inObject keys:(NSSet *)inModifiedKeys silent:(BOOL)silent
89 NSSet *modifiedAttributes = nil;
92 if(inModifiedKeys == nil ||
93 (showIdle && [inModifiedKeys containsObject:@"Idle"]) ||
94 (showStatus && ([inModifiedKeys containsObject:@"StatusMessage"] ||
95 [inModifiedKeys containsObject:@"ContactListStatusMessage"] ||
96 [inModifiedKeys containsObject:@"StatusName"]))){
97 NSMutableString *statusMessage = nil;
98 NSString *finalMessage = nil;
102 NSAttributedString *attributedStatusMessage = [[adium contentController] filterAttributedString:[(AIListContact *)inObject contactListStatusMessage]
103 usingFilterType:AIFilterDisplay
104 direction:AIFilterIncoming
106 //Convert attachments to strings so emoticons become their text equivalents, etc.
107 attributedStatusMessage = [attributedStatusMessage attributedStringByConvertingAttachmentsToStrings];
109 statusMessage = [[[[attributedStatusMessage string] stringByTrimmingCharactersInSet:whitespaceAndNewlineCharacterSet] mutableCopy] autorelease];
111 //Incredibly long status messages are slow to size, so we crop them to a reasonable length
112 if([statusMessage length] > STATUS_MAX_LENGTH){
113 [statusMessage deleteCharactersInRange:NSMakeRange(STATUS_MAX_LENGTH,
114 [statusMessage length] - STATUS_MAX_LENGTH)];
117 /* Linebreaks in the status message cause vertical alignment issues.
118 * We will replace line breaks with '/' as is done with multiple lines of a poem displayed on a single line.
120 * First, we remove duplicate linebreaks. */
121 while([statusMessage replaceOccurrencesOfString:@"\r\r"
123 options:NSLiteralSearch
124 range:NSMakeRange(0,[statusMessage length])]);
125 while([statusMessage replaceOccurrencesOfString:@"\n\n"
127 options:NSLiteralSearch
128 range:NSMakeRange(0,[statusMessage length])]);
129 while([statusMessage replaceOccurrencesOfString:@"\r\n"
131 options:NSLiteralSearch
132 range:NSMakeRange(0,[statusMessage length])]);
134 [statusMessage replaceOccurrencesOfString:@"\r"
136 options:NSLiteralSearch
137 range:NSMakeRange(0,[statusMessage length])];
138 [statusMessage replaceOccurrencesOfString:@"\n"
140 options:NSLiteralSearch
141 range:NSMakeRange(0,[statusMessage length])];
144 idle = (showIdle ? [inObject integerStatusObjectForKey:@"Idle"] : 0);
147 if(idle > 0 && statusMessage){
148 finalMessage = [NSString stringWithFormat:@"(%@) %@",[self idleStringForSeconds:idle], statusMessage];
150 finalMessage = [NSString stringWithFormat:@"(%@)",[self idleStringForSeconds:idle]];
152 finalMessage = statusMessage;
155 [[inObject displayArrayForKey:@"ExtendedStatus"] setObject:finalMessage withOwner:self];
156 modifiedAttributes = [NSSet setWithObject:@"ExtendedStatus"];
159 return(modifiedAttributes);
164 * @brief Determine the idle string
166 * @param seconds Number of seconds idle
167 * @result A localized string to display for the idle time
169 - (NSString *)idleStringForSeconds:(int)seconds
171 NSString *idleString;
173 //Create the idle string
174 if(seconds > 599400){//Cap idle at 999 Hours (999*60*60 seconds)
175 idleString = AILocalizedString(@"Idle",nil);
176 }else if(seconds >= 600){
177 idleString = [NSString stringWithFormat:@"%ih",seconds / 60];
178 }else if(seconds >= 60){
179 idleString = [NSString stringWithFormat:@"%i:%02i",seconds / 60, seconds % 60];
181 idleString = [NSString stringWithFormat:@"%i",seconds];