Bug Summary

File:Source/AIAddressBookUserIconSource.m
Location:line 73, column 11
Description:dead store

Annotated Source Code

1//
2// AIAddressBookUserIconSource.m
3// Adium
4//
5// Created by Evan Schoenberg on 1/4/08.
6//
7
8#import "AIAddressBookUserIconSource.h"
9#import "ESAddressBookIntegrationPlugin.h"
10#import <Adium/AIPreferenceControllerProtocol.h>
11#import <AddressBook/AddressBook.h>
12#import <Adium/AIUserIcons.h>
13#import <Adium/AIMetaContact.h>
14#import <AIUtilities/AIImageDrawingAdditions.h>
15
16#define KEY_AB_IMAGE_SYNC @"AB Image Sync"
17#define KEY_AB_PREFER_ADDRESS_BOOK_IMAGES @"AB Prefer AB Images"
18
19@interface AIAddressBookUserIconSource (PRIVATE)
20- (BOOL)updateFromLocalImageForPerson:(ABPerson *)person object:(AIListObject *)inObject;
21@end
22
23@implementation AIAddressBookUserIconSource
24
25- (id)init
26{
27 if ((self = [super init])) {
28 //Tracking dictionary for asynchronous image loads
29 trackingDict = [[NSMutableDictionary alloc] init];
30 trackingDictPersonToTagNumber = [[NSMutableDictionary alloc] init];
31 trackingDictTagNumberToPerson = [[NSMutableDictionary alloc] init];
32 priority = AIUserIconLowPriority0.75;
33
34 [[adium preferenceController] registerPreferenceObserver:self forGroup:PREF_GROUP_ADDRESSBOOK@ "Address Book"];
35 }
36
37 return self;
38}
39
40- (void)dealloc
41{
42 [trackingDictPersonToTagNumber release]; trackingDictPersonToTagNumber = nil0;
43 [trackingDictTagNumberToPerson release]; trackingDictTagNumberToPerson = nil0;
44
45 [super dealloc];
46}
47
48/*!
49 * @brief AIUserIcons wants this source to update its user icon for an object
50 *
51 * Call +[AIUserIcons userIconSource:didDetermineUserIcon:asynchronously:forObject:] with the new icon, if appropriate
52 *
53 * @result An AIUserIconSourceQueryResult indicating the result
54 */
55- (AIUserIconSourceQueryResult)updateUserIconForObject:(AIListObject *)inObject
56{
57 if (!useABImages)
58 return AIUserIconSourceDidNotFindIcon;
59
60 ABPerson *person = [[ESAddressBookIntegrationPlugin class] personForListObject:inObject];
61
62 if (!person)
63 return AIUserIconSourceDidNotFindIcon;
64
65 /* Some mild complexity here. If inObject is a metacontact, we should only proceed if
66 * none of its contained contacts have a higher-priority user icon than we will be.
67 * This prevents a metacontact-associated address book image from overriding a serverside
68 * contained-contact image if that isn't the sort of thing that the user might be into.
69 */
70 if ([inObject isKindOfClass:[AIMetaContact class]]) {
71 NSEnumerator *enumerator = [[(AIMetaContact *)inObject listContacts] objectEnumerator];
72 AIListContact *listContact;
Although the value stored to 'listContact' is used in the enclosing expression, the value is never actually read from 'listContact'
73 while ((listContact = [enumerator nextObject])) {
74 if (![AIUserIcons userIconSource:self changeWouldBeRelevantForObject:inObject])
75 return AIUserIconSourceDidNotFindIcon;
76 }
77 }
78
79 if ([self updateFromLocalImageForPerson:person
80 object:inObject]) {
81 return AIUserIconSourceFoundIcon;
82
83 } else if ([self queueDelayedFetchOfImageFromAnySourceForPerson:person
84 object:inObject]) {
85 return AIUserIconSourceLookingUpIconAsynchronously;
86
87 } else {
88 return AIUserIconSourceDidNotFindIcon;
89 }
90}
91
92/*!
93 * @brief The priority at which this source should be used. See the #defines in AIUserIcons.h for posible values.
94 */
95- (AIUserIconPriority)priority
96{
97 return priority;
98}
99
100#pragma mark -
101
102- (void)preferencesChangedForGroup:(NSString *)group key:(NSString *)key
103 object:(AIListObject *)object preferenceDict:(NSDictionary *)prefDict firstTime:(BOOL)firstTime
104{
105 if (object) {
106 [AIUserIcons userIconSource:self didChangeForObject:object];
107
108 } else {
109 AIUserIconPriority oldPriority = priority;
110 BOOL oldUseABImages = useABImages;
111
112 preferAddressBookImages = [[prefDict objectForKey:KEY_AB_PREFER_ADDRESS_BOOK_IMAGES@ "AB Prefer AB Images"] boolValue];
113 useABImages = [[prefDict objectForKey:KEY_AB_USE_IMAGES@ "AB Use AB Images"] boolValue];
114
115 priority = (preferAddressBookImages ? AIUserIconHighPriority0.25 : AIUserIconLowPriority0.75);
116 if ((priority != oldPriority) || (oldUseABImages != useABImages)) {
117 [AIUserIcons userIconSource:self priorityDidChange:priority fromPriority:oldPriority];
118 }
119 }
120}
121
122#pragma mark Address Book
123/*!
124 * @brief Called when the address book completes an asynchronous image lookup
125 *
126 * @param inData NSData representing an NSImage
127 * @param tag A tag indicating the lookup with which this call is associated. We use a tracking dictionary, trackingDict, to associate this int back to a usable object.
128 */
129- (void)consumeImageData:(NSData *)inData forTag:(int)tag
130{
131 if (useABImages) {
132 NSNumber *tagNumber;
133 NSImage *image;
134 AIListObject *listObject;
135 // AIListContact *parentContact;
136 NSString *uniqueID;
137 id setOrObject;
138
139 tagNumber = [NSNumber numberWithInt:tag];
140
141 //Apply the image to the appropriate listObject
142 image = (inData ? [[[NSImage alloc] initWithData:inData] autorelease] : nil0);
143
144 //Address book can feed us giant images, which we really don't want to keep around
145 NSSize size = [image size];
146 if (size.width > 96 || size.height > 96)
147 image = [image imageByScalingToSize:NSMakeSize(96, 96)];
148
149 //Get the object from our tracking dictionary
150 setOrObject = [trackingDict objectForKey:tagNumber];
151
152 if ([setOrObject isKindOfClass:[AIListObject class]]) {
153 listObject = (AIListObject *)setOrObject;
154
155 [AIUserIcons userIconSource:self
156 didDetermineUserIcon:image
157 asynchronously:YES( BOOL ) 1
158 forObject:listObject];
159
160 } else /*if ([setOrObject isKindOfClass:[NSSet class]])*/{
161 NSEnumerator *enumerator;
162
163 //Apply the image to each listObject at the appropriate priority
164 enumerator = [(NSSet *)setOrObject objectEnumerator];
165 while ((listObject = [enumerator nextObject])) {
166 [AIUserIcons userIconSource:self
167 didDetermineUserIcon:image
168 asynchronously:YES( BOOL ) 1
169 forObject:listObject];
170 }
171 }
172
173 //No further need for the dictionary entries
174 [trackingDict removeObjectForKey:tagNumber];
175
176 if ((uniqueID = [trackingDictTagNumberToPerson objectForKey:tagNumber])) {
177 [trackingDictPersonToTagNumber removeObjectForKey:uniqueID];
178 [trackingDictTagNumberToPerson removeObjectForKey:tagNumber];
179 }
180 }
181}
182
183/*!
184 * @brief Queue an asynchronous image fetch for person associated with inObject
185 *
186 * Image lookups are done asynchronously. This allows other processing to be done between image calls, improving the perceived
187 * speed. [Evan: I have seen one instance of this being problematic. My localhost loop was broken due to odd network problems,
188 * and the asynchronous lookup therefore hung the problem. Submitted as radar 3977541.]
189 *
190 * We load from the same ABPerson for multiple AIListObjects, one for each service/UID combination times
191 * the number of accounts on that service. We therefore aggregate the lookups to lower the address book search
192 * and image/data creation overhead.
193 *
194 * @param person The ABPerson to fetch the image from
195 * @param inObject The AIListObject with which to ultimately associate the image
196 */
197- (BOOL)queueDelayedFetchOfImageFromAnySourceForPerson:(ABPerson *)person object:(AIListObject *)inObject
198{
199 int tag;
200 NSNumber *tagNumber;
201 NSString *uniqueId;
202
203 uniqueId = [person uniqueId];
204
205 //Check if we already have a tag for the loading of another object with the same
206 //internalObjectID
207 if ((tagNumber = [trackingDictPersonToTagNumber objectForKey:uniqueId])) {
208 id previousValue;
209 NSMutableSet *objectSet;
210
211 previousValue = [trackingDict objectForKey:tagNumber];
212
213 if ([previousValue isKindOfClass:[AIListObject class]]) {
214 //If the old value is just a listObject, create an array with the old object
215 //and the new object
216 if (previousValue != inObject) {
217 objectSet = [NSMutableSet setWithObjects:previousValue,inObject,nil0];
218
219 //Store the array in the tracking dict
220 [trackingDict setObject:objectSet forKey:tagNumber];
221 }
222
223 } else /*if ([previousValue isKindOfClass:[NSMutableArray class]])*/{
224 //Add the new object to the previously-created array
225 [(NSMutableSet *)previousValue addObject:inObject];
226 }
227
228 } else {
229 //Begin the image load
230 tag = [person beginLoadingImageDataForClient:self];
231 tagNumber = [NSNumber numberWithInt:tag];
232
233 //We need to be able to take a tagNumber and retrieve the object
234 [trackingDict setObject:inObject forKey:tagNumber];
235
236 //We also want to take a person's uniqueID and potentially find an existing tag number
237 [trackingDictPersonToTagNumber setObject:tagNumber forKey:uniqueId];
238 [trackingDictTagNumberToPerson setObject:uniqueId forKey:tagNumber];
239 }
240
241 return YES( BOOL ) 1;
242}
243
244- (BOOL)updateFromLocalImageForPerson:(ABPerson *)person object:(AIListObject *)inObject
245{
246 NSData *imageData = [person imageData];
247 NSImage *image = (imageData ? [[[NSImage alloc] initWithData:imageData] autorelease] : nil0);
248
249 //Address book can feed us giant images, which we really don't want to keep around
250 if (image) {
251 NSSize size = [image size];
252 if (size.width > 96 || size.height > 96)
253 image = [image imageByScalingToSize:NSMakeSize(96, 96)];
254
255 [AIUserIcons userIconSource:self
256 didDetermineUserIcon:image
257 asynchronously:NO( BOOL ) 0
258 forObject:inObject];
259
260 int tag;
261 if ((tag = [[trackingDictPersonToTagNumber objectForKey:[person uniqueId]] intValue])) {
262 [ABPerson cancelLoadingImageDataForTag:tag];
263 }
264
265 return YES( BOOL ) 1;
266
267 } else {
268 return NO( BOOL ) 0;
269 }
270}
271
272@end