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 <AIUtilities/AIDateFormatterAdditions.h>
25 #import <Adium/AIAbstractListController.h>
26 #import <Adium/AIListObject.h>
27 #import <Adium/AIListContact.h>
29 #define STATUS_MAX_LENGTH 100
31 @interface AIExtendedStatusPlugin (PRIVATE)
32 - (void)preferencesChanged:(NSNotification *)notification;
36 * @class AIExtendedStatusPlugin
37 * @brief Manage the 'extended status' shown in the contact list
39 * If the contact list layout calls for displaying a status message or idle time (or both), this component manages
40 * generating the appropriate string, storing it in the @"ExtendedStatus" status object, and updating it as necessary.
42 @implementation AIExtendedStatusPlugin
49 [[adium preferenceController] registerPreferenceObserver:self forGroup:PREF_GROUP_LIST_LAYOUT];
51 whitespaceAndNewlineCharacterSet = [[NSCharacterSet whitespaceAndNewlineCharacterSet] retain];
57 - (void)uninstallPlugin
59 [[adium preferenceController] unregisterPreferenceObserver:self];
60 [[adium contactController] unregisterListObjectObserver:self];
64 * @brief Preferences changes
66 * PREF_GROUP_LIST_LAYOUT changed; update our list objects if needed.
68 - (void)preferencesChangedForGroup:(NSString *)group key:(NSString *)key
69 object:(AIListObject *)object preferenceDict:(NSDictionary *)prefDict firstTime:(BOOL)firstTime
71 BOOL oldShowStatus = showStatus;
72 BOOL oldShowIdle = showIdle;
74 EXTENDED_STATUS_STYLE statusStyle = [[prefDict objectForKey:KEY_LIST_LAYOUT_EXTENDED_STATUS_STYLE] intValue];
75 showStatus = ((statusStyle == STATUS_ONLY) || (statusStyle == IDLE_AND_STATUS));
76 showIdle = ((statusStyle == IDLE_ONLY) || (statusStyle == IDLE_AND_STATUS));
79 [[adium contactController] registerListObjectObserver:self];
81 if ((oldShowStatus != showStatus) || (oldShowIdle != showIdle)) {
82 [[adium contactController] updateAllListObjectsForObserver:self];
88 * @brief Update list object's extended status messages
90 - (NSSet *)updateListObject:(AIListObject *)inObject keys:(NSSet *)inModifiedKeys silent:(BOOL)silent
92 NSSet *modifiedAttributes = nil;
94 /* Work at the parent contact (metacontact, etc.) level for extended status, since that's what's displayed in the contact list.
95 * We completely ignore status updates sent for an object which isn't the highest-level up (e.g. is within a metacontact).
97 if ((inModifiedKeys == nil ||
98 (showIdle && [inModifiedKeys containsObject:@"Idle"]) ||
99 (showStatus && ([inModifiedKeys containsObject:@"StatusMessage"] ||
100 [inModifiedKeys containsObject:@"ContactListDisplayName"] ||
101 [inModifiedKeys containsObject:@"StatusName"]))) &&
102 [inObject isKindOfClass:[AIListContact class]] &&
103 ([(AIListContact *)inObject parentContact] == inObject)) {
104 NSMutableString *statusMessage = nil;
105 NSString *finalMessage = nil;
109 NSAttributedString *filteredMessage;
111 filteredMessage = [[adium contentController] filterAttributedString:[(AIListContact *)inObject contactListStatusMessage]
112 usingFilterType:AIFilterContactList
113 direction:AIFilterIncoming
115 statusMessage = [[[[filteredMessage string] stringByTrimmingCharactersInSet:whitespaceAndNewlineCharacterSet] mutableCopy] autorelease];
117 //Incredibly long status messages are slow to size, so we crop them to a reasonable length
118 int statusMessageLength = [statusMessage length];
119 if (statusMessageLength == 0) {
122 } else if (statusMessageLength > STATUS_MAX_LENGTH) {
123 [statusMessage deleteCharactersInRange:NSMakeRange(STATUS_MAX_LENGTH,
124 [statusMessage length] - STATUS_MAX_LENGTH)];
127 /* Linebreaks in the status message cause vertical alignment issues. */
128 [statusMessage convertNewlinesToSlashes];
131 idle = (showIdle ? [inObject integerStatusObjectForKey:@"Idle"] : 0);
134 if (idle > 0 && statusMessage) {
135 finalMessage = [NSString stringWithFormat:@"(%@) %@",[self idleStringForMinutes:idle], statusMessage];
136 } else if (idle > 0) {
137 finalMessage = [NSString stringWithFormat:@"(%@)",[self idleStringForMinutes:idle]];
139 finalMessage = statusMessage;
142 [[inObject displayArrayForKey:@"ExtendedStatus"] setObject:finalMessage withOwner:self];
143 modifiedAttributes = [NSSet setWithObject:@"ExtendedStatus"];
146 return modifiedAttributes;
151 * @brief Determine the idle string
153 * @param minutes Number of minutes idle
154 * @result A localized string to display for the idle time
156 - (NSString *)idleStringForMinutes:(int)minutes //input is actualy minutes
158 // Cap Idletime at 599400 minutes (999 hours)
159 return ((minutes > 599400) ? AILocalizedString(@"Idle",nil) : [NSDateFormatter stringForApproximateTimeInterval:(minutes * 60) abbreviated:YES]);