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 "AIExtendedStatusPlugin.h"
18 #import <Adium/AIContactControllerProtocol.h>
19 #import <Adium/AIContentControllerProtocol.h>
20 #import <Adium/AIPreferenceControllerProtocol.h>
21 #import <AIUtilities/AIMutableOwnerArray.h>
22 #import <AIUtilities/AIAttributedStringAdditions.h>
23 #import <AIUtilities/AIMutableStringAdditions.h>
24 #import <Adium/AIAbstractListController.h>
25 #import <Adium/AIListObject.h>
26 #import <Adium/AIListContact.h>
28 #define STATUS_MAX_LENGTH 100
30 @interface AIExtendedStatusPlugin (PRIVATE)
31 - (void)preferencesChanged:(NSNotification *)notification;
35 * @class AIExtendedStatusPlugin
36 * @brief Manage the 'extended status' shown in the contact list
38 * If the contact list layout calls for displaying a status message or idle time (or both), this component manages
39 * generating the appropriate string, storing it in the @"ExtendedStatus" status object, and updating it as necessary.
41 @implementation AIExtendedStatusPlugin
48 [[adium preferenceController] registerPreferenceObserver:self forGroup:PREF_GROUP_LIST_LAYOUT];
50 whitespaceAndNewlineCharacterSet = [[NSCharacterSet whitespaceAndNewlineCharacterSet] retain];
56 - (void)uninstallPlugin
58 [[adium preferenceController] unregisterPreferenceObserver:self];
59 [[adium contactController] unregisterListObjectObserver:self];
63 * @brief Preferences changes
65 * PREF_GROUP_LIST_LAYOUT changed; update our list objects if needed.
67 - (void)preferencesChangedForGroup:(NSString *)group key:(NSString *)key
68 object:(AIListObject *)object preferenceDict:(NSDictionary *)prefDict firstTime:(BOOL)firstTime
70 BOOL oldShowStatus = showStatus;
71 BOOL oldShowIdle = showIdle;
73 EXTENDED_STATUS_STYLE statusStyle = [[prefDict objectForKey:KEY_LIST_LAYOUT_EXTENDED_STATUS_STYLE] intValue];
74 showStatus = ((statusStyle == STATUS_ONLY) || (statusStyle == IDLE_AND_STATUS));
75 showIdle = ((statusStyle == IDLE_ONLY) || (statusStyle == IDLE_AND_STATUS));
78 [[adium contactController] registerListObjectObserver:self];
80 if ((oldShowStatus != showStatus) || (oldShowIdle != showIdle)) {
81 [[adium contactController] updateAllListObjectsForObserver:self];
87 * @brief Update list object's extended status messages
89 - (NSSet *)updateListObject:(AIListObject *)inObject keys:(NSSet *)inModifiedKeys silent:(BOOL)silent
91 NSSet *modifiedAttributes = nil;
94 if ((inModifiedKeys == nil ||
95 (showIdle && [inModifiedKeys containsObject:@"Idle"]) ||
96 (showStatus && ([inModifiedKeys containsObject:@"StatusMessage"] ||
97 [inModifiedKeys containsObject:@"ContactListDisplayName"] ||
98 [inModifiedKeys containsObject:@"StatusName"]))) &&
99 [inObject isKindOfClass:[AIListContact class]]){
100 NSMutableString *statusMessage = nil;
101 NSString *finalMessage = nil;
104 //Work at the parent contact (metacontact, etc.) level for extended status, since that's what's displayed in the contact list
105 inObject = [(AIListContact *)inObject parentContact];
108 NSAttributedString *filteredMessage;
110 filteredMessage = [[adium contentController] filterAttributedString:[(AIListContact *)inObject contactListStatusMessage]
111 usingFilterType:AIFilterContactList
112 direction:AIFilterIncoming
114 statusMessage = [[[[filteredMessage string] stringByTrimmingCharactersInSet:whitespaceAndNewlineCharacterSet] mutableCopy] autorelease];
116 //Incredibly long status messages are slow to size, so we crop them to a reasonable length
117 if ([statusMessage length] > STATUS_MAX_LENGTH) {
118 [statusMessage deleteCharactersInRange:NSMakeRange(STATUS_MAX_LENGTH,
119 [statusMessage length] - STATUS_MAX_LENGTH)];
122 /* Linebreaks in the status message cause vertical alignment issues. */
123 [statusMessage convertNewlinesToSlashes];
126 idle = (showIdle ? [inObject integerStatusObjectForKey:@"Idle"] : 0);
129 if (idle > 0 && statusMessage) {
130 finalMessage = [NSString stringWithFormat:@"(%@) %@",[self idleStringForSeconds:idle], statusMessage];
131 } else if (idle > 0) {
132 finalMessage = [NSString stringWithFormat:@"(%@)",[self idleStringForSeconds:idle]];
134 finalMessage = statusMessage;
137 [[inObject displayArrayForKey:@"ExtendedStatus"] setObject:finalMessage withOwner:self];
138 modifiedAttributes = [NSSet setWithObject:@"ExtendedStatus"];
141 return modifiedAttributes;
146 * @brief Determine the idle string
148 * @param seconds Number of seconds idle
149 * @result A localized string to display for the idle time
151 - (NSString *)idleStringForSeconds:(int)seconds
153 NSString *idleString;
155 //Create the idle string
156 if (seconds > 599400) {//Cap idle at 999 Hours (999*60*60 seconds)
157 idleString = AILocalizedString(@"Idle",nil);
158 } else if (seconds >= 600) {
159 idleString = [NSString stringWithFormat:@"%ih",seconds / 60];
160 } else if (seconds >= 60) {
161 idleString = [NSString stringWithFormat:@"%i:%02i",seconds / 60, seconds % 60];
163 idleString = [NSString stringWithFormat:@"%i",seconds];