William Bowling is sharing code with you
Bitbucket is a code hosting site. Unlimited public and private repositories. Free for small teams.
Don't show this again1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 | /*
* 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/AIContactControllerProtocol.h>
#import <Adium/AIMenuControllerProtocol.h>
#import "CBContactCountingDisplayPlugin.h"
#import <AIUtilities/AIDictionaryAdditions.h>
#import <AIUtilities/AIMenuAdditions.h>
#import <AIUtilities/AIMutableOwnerArray.h>
#import <Adium/AIAccount.h>
#import <Adium/AIListContact.h>
#import <Adium/AIListObject.h>
#import <Adium/AIListGroup.h>
#define CONTACT_COUNTING_DISPLAY_DEFAULT_PREFS @"ContactCountingDisplayDefaults"
#define SHOW_COUNT_ONLINE_CONTACTS_TITLE AILocalizedString(@"Show Group Online Count", nil)
#define SHOW_COUNT_ALL_CONTACTS_TITLE AILocalizedString(@"Show Group Total Count", nil)
#define KEY_COUNT_ALL_CONTACTS @"Count All Contacts"
#define KEY_COUNT_ONLINE_CONTACTS @"Count Online Contacts"
#define KEY_HIDE_CONTACT_LIST_GROUPS @"Hide Contact List Groups"
/*!
* @class CBContactCountingDisplayPlugin
*
* @brief Component to handle displaying counts of contacts, both online and total, next to group names
*
* This componenet adds two menu items, "Count All Contacts" and "Count Online Contacts." Both default to being off.
* When on, these options display the appropriate count for an AIListGroup's contained objects.
*/
@implementation CBContactCountingDisplayPlugin
/*!
* @brief Install
*/
- (void)installPlugin
{
//register our defaults
[adium.preferenceController registerDefaults:[NSDictionary dictionaryNamed:CONTACT_COUNTING_DISPLAY_DEFAULT_PREFS
forClass:[self class]]
forGroup:PREF_GROUP_CONTACT_LIST];
//init our menu items
menuItem_countOnlineObjects = [[NSMenuItem alloc] initWithTitle:SHOW_COUNT_ONLINE_CONTACTS_TITLE
target:self
action:@selector(toggleMenuItem:)
keyEquivalent:@""];
[adium.menuController addMenuItem:menuItem_countOnlineObjects toLocation:LOC_View_Counting_Toggles];
menuItem_countAllObjects = [[NSMenuItem alloc] initWithTitle:SHOW_COUNT_ALL_CONTACTS_TITLE
target:self
action:@selector(toggleMenuItem:)
keyEquivalent:@""];
[adium.menuController addMenuItem:menuItem_countAllObjects toLocation:LOC_View_Counting_Toggles];
//set up the prefs
countAllObjects = NO;
countOnlineObjects = NO;
[adium.preferenceController registerPreferenceObserver:self forGroup:PREF_GROUP_CONTACT_LIST];
[adium.preferenceController registerPreferenceObserver:self forGroup:PREF_GROUP_CONTACT_LIST_DISPLAY];
[[AIContactObserverManager sharedManager] registerListObjectObserver:self];
}
/*!
* @brief Preferences changed
*
* PREF_GROUP_CONTACT_LIST preferences changed; update our counting display as necessary.
*/
- (void)preferencesChangedForGroup:(NSString *)group key:(NSString *)key
object:(AIListObject *)object preferenceDict:(NSDictionary *)prefDict firstTime:(BOOL)firstTime
{
// Don't update for specific objects.
if (object != nil)
return;
if ([group isEqualToString:PREF_GROUP_CONTACT_LIST] &&
([key isEqualToString:KEY_COUNT_ONLINE_CONTACTS] || [key isEqualToString:KEY_COUNT_ALL_CONTACTS] || firstTime)) {
countAllObjects = [[prefDict objectForKey:KEY_COUNT_ALL_CONTACTS] boolValue];
countOnlineObjects = [[prefDict objectForKey:KEY_COUNT_ONLINE_CONTACTS] boolValue];
[[AIContactObserverManager sharedManager] updateAllListObjectsForObserver:self];
[menuItem_countOnlineObjects setState:countOnlineObjects];
[menuItem_countAllObjects setState:countAllObjects];
} else if (([group isEqualToString:PREF_GROUP_CONTACT_LIST_DISPLAY]) &&
(!key || [key isEqualToString:KEY_HIDE_CONTACT_LIST_GROUPS])) {
showingGroups = ![[prefDict objectForKey:KEY_HIDE_CONTACT_LIST_GROUPS] boolValue];
}
}
/*!
* @brief Update the counts when a group changes its object count or a contact signs on or off
*/
- (NSSet *)updateListObject:(AIListObject *)inObject keys:(NSSet *)inModifiedKeys silent:(BOOL)silent
{
NSMutableSet *groups = [NSMutableSet set];
//We never update for an AIAccount object
if ([inObject isKindOfClass:[AIListContact class]] && [inModifiedKeys containsObject:@"Online"]) {
// We need to update *all* of this contact's groups for its online change.
[groups unionSet:inObject.groups];
} else if ([inObject isKindOfClass:[AIListGroup class]]
&& (!inModifiedKeys || ([inModifiedKeys containsObject:@"ObjectCount"] || [inModifiedKeys containsObject:@"VisibleObjectCount"]))
&& ![inObject.UID isEqualToString:ADIUM_ROOT_GROUP_NAME]) {
/* We check against a nil inModifiedKeys so we can remove our Counting information from the display when the user
* toggles it off.
*
* We update for any group which isn't the root group when its contained objects count changes.
*/
[groups addObject:inObject];
} else {
// We don't need to update anything.
return nil;
}
for (AIListGroup *inGroup in groups) {
NSString *countString = nil;
NSUInteger onlineObjects = [[inGroup.visibleContainedObjects valueForKeyPath:@"@sum.Online"] integerValue];
NSUInteger totalObjects = inGroup.countOfContainedObjects;
/*
* Create our count string for displaying in the list group's cell
* If the number of online objects is the same as the number of total objects, just display one number.
* If the group is the offline group, just display the number of total objects if we should.
*/
if (countOnlineObjects && countAllObjects && (onlineObjects != totalObjects) && (inGroup != adium.contactController.offlineGroup)) {
countString = [NSString stringWithFormat:AILocalizedString(@"%lu of %lu", "Used in the display for the contact list for the number of online contacts out of the number of total contacts"),
onlineObjects, totalObjects];
} else if (countAllObjects) {
countString = [NSString stringWithFormat:@"%lu", totalObjects];
} else if (inGroup != adium.contactController.offlineGroup) {
countString = [NSString stringWithFormat:@"%lu", onlineObjects];
} else {
countString = [NSString stringWithString:@""];
}
[inGroup setValue:countString
forProperty:@"Count Text"
notify:NotifyNever];
[inGroup setValue:[NSNumber numberWithBool:(countOnlineObjects || countAllObjects)]
forProperty:@"Show Count"
notify:NotifyNever];
[[AIContactObserverManager sharedManager] listObjectAttributesChanged:inGroup
modifiedKeys:[NSSet setWithObject:@"Count Text"]];
}
return nil;
}
/*!
* @brief User toggled one of our two menu items
*/
- (void)toggleMenuItem:(id)sender
{
if (sender == menuItem_countOnlineObjects) {
BOOL newPref = !countOnlineObjects;
//Toggle and set, which will call back on preferencesChanged: above
[adium.preferenceController setPreference:[NSNumber numberWithBool:newPref]
forKey:KEY_COUNT_ONLINE_CONTACTS
group:PREF_GROUP_CONTACT_LIST];
} else if (sender == menuItem_countAllObjects) {
BOOL newPref = !countAllObjects;
//Toggle and set, which will call back on preferencesChanged: above
[adium.preferenceController setPreference:[NSNumber numberWithBool:newPref]
forKey:KEY_COUNT_ALL_CONTACTS
group:PREF_GROUP_CONTACT_LIST];
}
}
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem
{
if ((menuItem == menuItem_countOnlineObjects) || (menuItem == menuItem_countAllObjects)) {
return showingGroups;
}
return YES;
}
/*
* Uninstall
*/
- (void)uninstallPlugin
{
//we are no longer an observer
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[AIContactObserverManager sharedManager] unregisterListObjectObserver:self];
[adium.preferenceController unregisterPreferenceObserver:self];
}
@end
|