// // AILogSizeSort.m // SortByLogSizePlugin // // Created by Jon Chambers on 9/28/08. // Copyright 2008 Jon Chambers. All rights reserved. // #import "AILogSizeSort.h" #import "AILoggerPlugin.h" #import #import #import #import #import #import @implementation AILogSizeSort /*! * @brief Did become active first time * * Called only once; gives the sort controller an opportunity to set defaults and load preferences lazily. */ - (void)didBecomeActiveFirstTime { } /*! * @brief Non-localized identifier */ - (NSString *)identifier{ return @"Log size"; } /*! * @brief Localized display name */ - (NSString *)displayName{ return AILocalizedString(@"Sort Contacts by Log Size",nil); } /*! * @brief Properties which, when changed, should trigger a resort */ - (NSSet *)statusKeysRequiringResort{ return nil; } /*! * @brief Attribute keys which, when changed, should trigger a resort */ - (NSSet *)attributeKeysRequiringResort{ return nil; } #pragma mark Configuration /*! * @brief Window title when configuring the sort * * Subclasses should provide a title for configuring the sort only if configuration is possible. * @result Localized title. If nil, the menu item will be disabled. */ - (NSString *)configureSortWindowTitle{ return nil; } /*! * @brief Nib name for configuration */ - (NSString *)configureNibName{ return nil; } /*! * @brief View did load */ - (void)viewDidLoad{ } /*! * @brief Preference changed * * Sort controllers should live update as preferences change. */ - (IBAction)changePreference:(id)sender { } /*! * Allow users to manually sort groups. */ -(BOOL)canSortManually { return YES; } /** * Returns the total aggregate log size for a contact. For meta-contacts, the * total log file size of all sub-contacts is returned. If no log exists or if * something else goes wrong, 0 is returned. * * @param listObject an AIListContact for which to retrieve a total log file size * @return the total log file size in bytes or 0 if an error occurred */ +(unsigned long long)getContactLogSize:(AIListContact *)listObject { NSFileManager *fileManager = [NSFileManager defaultManager]; if([listObject isMemberOfClass:[AIMetaContact class]]) { // Recurse through all sub-contacts id contact; unsigned long long size = 0; NSEnumerator *contactEnumerator = [[listObject listContacts] objectEnumerator]; while(contact = [contactEnumerator nextObject]) { size += [AILogSizeSort getContactLogSize:contact]; } return size; } else { // Find the path to the directory containing the log files for this contact NSString *path = [[AILoggerPlugin logBasePath] stringByAppendingPathComponent:[AILoggerPlugin relativePathForLogWithObject:[listObject UID] onAccount: [listObject account]]]; // Grab an enumerator for all log files for this contact NSDirectoryEnumerator *dirEnum = [[NSFileManager defaultManager] enumeratorAtPath:path]; NSString *file; unsigned long long size = 0; while(file = [dirEnum nextObject]) { NSDictionary *fileAttributes = [fileManager fileAttributesAtPath:[path stringByAppendingPathComponent:file] traverseLink:YES]; if (fileAttributes != nil) { NSNumber *fileSize; if(fileSize = [fileAttributes objectForKey:NSFileSize]) { size += [fileSize unsignedLongLongValue]; } } } return size; } } #pragma mark Sorting /*! * @brief Alphabetical sort */ int logSizeSort(id objectA, id objectB, BOOL groups) { if(groups) { // Keep groups in manual order (borrowed from ESStatusSort) if ([objectA orderIndex] > [objectB orderIndex]) { return NSOrderedDescending; } else { return NSOrderedAscending; } } NSNumber *sizeA = [NSNumber numberWithUnsignedLongLong:[AILogSizeSort getContactLogSize:objectA]]; NSNumber *sizeB = [NSNumber numberWithUnsignedLongLong:[AILogSizeSort getContactLogSize:objectB]]; if([sizeB compare:sizeA] == NSOrderedSame) { // Fall back to basic alphabetical sorting in the event of a tie. return [[objectA displayName] caseInsensitiveCompare:[objectB displayName]]; } else { // There's a clear winner; run with it. return [sizeB compare:sizeA]; } } /*! * @brief Sort function */ - (sortfunc)sortFunction{ return &logSizeSort; } @end