X-Git-Url: https://code.grnet.gr/git/pithos-macos/blobdiff_plain/904acde2af10b0b059ee38d92e175a6f2542c589..cb6abe7283fd973e5dacbbf7a8bc920fd2eed089:/pithos-macos/PithosPreferencesController.m diff --git a/pithos-macos/PithosPreferencesController.m b/pithos-macos/PithosPreferencesController.m index 4cbf3ac..c978c02 100644 --- a/pithos-macos/PithosPreferencesController.m +++ b/pithos-macos/PithosPreferencesController.m @@ -38,16 +38,41 @@ #import "PithosPreferencesController.h" #import "PithosBrowserController.h" #import "PithosAccountNode.h" +#import "PithosSharingAccountsNode.h" +#import "PithosContainerNode.h" +#import "PithosSubdirNode.h" +#import "PithosObjectNode.h" +#import "PithosEmptyNode.h" #import "PithosAccount.h" #import "pithos_macosAppDelegate.h" +#import "ImageAndTextCell.h" +@interface PithosPreferencesSyncOutlineViewCell : ImageAndTextCell {} +@end + +@implementation PithosPreferencesSyncOutlineViewCell + +- (void)setObjectValue:(id)object { + if ([object isKindOfClass:[PithosNode class]]) { + PithosNode *node = (PithosNode *)object; + [self setStringValue:node.displayName]; + [self setImage:node.icon]; + [self setEditable:NO]; + } else { + [super setObjectValue:object]; + } +} + +@end + @implementation PithosPreferencesController @synthesize selectedPithosAccount; @synthesize accountsArrayController; @synthesize accountRemoveEnable; @synthesize serverURL, authUser, authToken, manual, loginEnable, loginCancelEnable; +@synthesize syncActive, syncSkipHidden, syncDirectoryPath, syncAccountsDictionary, syncApplyEnable, syncCancelEnable, + syncAccountsOutlineView, syncAccountsRootFilesNodes; @synthesize groupsDictionaryController, selectedGroupMembersDictionaryController; -@synthesize syncActive, syncDirectoryPath, syncApplyEnable, syncCancelEnable; #pragma mark - #pragma mark Object Lifecycle @@ -65,7 +90,11 @@ // // Select the first tab when the window is loaded for the first time. // [[window valueForKeyPath:@"toolbar"] setSelectedItemIdentifier:@"0"]; - + + [[[syncAccountsOutlineView tableColumns] objectAtIndex:1] setDataCell:[[PithosPreferencesSyncOutlineViewCell alloc] init]]; + syncAccountsMyAccountNode = [[PithosEmptyNode alloc] initWithDisplayName:@"" + icon:[[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kUserIcon)]]; + [groupsDictionaryController setInitialKey:@"group"]; [groupsDictionaryController setInitialValue:@"user"]; [selectedGroupMembersDictionaryController setInitialKey:@"user"]; @@ -75,6 +104,10 @@ self.selectedPithosAccount = [[accountsArrayController selectedObjects] objectAtIndex:0]; [accountsArrayController addObserver:self forKeyPath:@"selection" options:NSKeyValueObservingOptionNew context:NULL]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(selectedPithosAccountNodeChildrenUpdated:) + name:@"SelectedPithosAccountNodeChildrenUpdated" + object:nil]; } - (BOOL)windowShouldClose:(id)sender { @@ -98,6 +131,11 @@ } } +- (void)selectedPithosAccountNodeChildrenUpdated:(NSNotification *)notification { + [syncAccountsOutlineView reloadData]; +// [syncAccountsOutlineView expandItem:nil expandChildren:YES]; +} + #pragma mark - #pragma Update @@ -117,12 +155,16 @@ BOOL isDirectory; self.syncApplyEnable = (selectedPithosAccount.active && ((selectedPithosAccount.syncActive != syncActive) || + (selectedPithosAccount.syncSkipHidden != syncSkipHidden) || (![selectedPithosAccount.syncDirectoryPath isEqualToString:syncDirectoryPath] && (![[NSFileManager defaultManager] fileExistsAtPath:syncDirectoryPath isDirectory:&isDirectory] || - isDirectory)))); + isDirectory)) || + ![selectedPithosAccount.syncAccountsDictionary isEqualToDictionary:syncAccountsDictionary])); self.syncCancelEnable = (selectedPithosAccount.active && ((selectedPithosAccount.syncActive != syncActive) || - ![selectedPithosAccount.syncDirectoryPath isEqualToString:syncDirectoryPath])); + (selectedPithosAccount.syncSkipHidden != syncSkipHidden) || + ![selectedPithosAccount.syncDirectoryPath isEqualToString:syncDirectoryPath] || + ![selectedPithosAccount.syncAccountsDictionary isEqualToDictionary:syncAccountsDictionary])); } #pragma mark - @@ -130,8 +172,11 @@ - (void)setSelectedPithosAccount:(PithosAccount *)aSelectedPithosAccount { if (aSelectedPithosAccount && ![aSelectedPithosAccount isEqualTo:selectedPithosAccount]) { - [selectedPithosAccount release]; - selectedPithosAccount = [aSelectedPithosAccount retain]; + selectedPithosAccount.accountNode.childrenUpdatedNotificationName = nil; + selectedPithosAccount.sharingAccountsNode.childrenUpdatedNotificationName = nil; + selectedPithosAccount = aSelectedPithosAccount; + selectedPithosAccount.accountNode.childrenUpdatedNotificationName = @"SelectedPithosAccountNodeChildrenUpdated"; + selectedPithosAccount.sharingAccountsNode.childrenUpdatedNotificationName = @"SelectedPithosAccountNodeChildrenUpdated"; [self updateAccounts]; [self loginCancel:self]; @@ -143,19 +188,16 @@ #pragma Login Properties - (void)setServerURL:(NSString *)aServerURL { - [serverURL release]; serverURL = [aServerURL copy]; [self updateLogin]; } - (void)setAuthUser:(NSString *)anAuthUser { - [authUser release]; authUser = [anAuthUser copy]; [self updateLogin]; } - (void)setAuthToken:(NSString *)anAuthToken { - [authToken release]; authToken = [anAuthToken copy]; [self updateLogin]; } @@ -164,8 +206,8 @@ manual = aManual; [self updateLogin]; if (!manual) { - self.authUser = [[selectedPithosAccount.authUser copy] autorelease]; - self.authToken = [[selectedPithosAccount.authToken copy] autorelease]; + self.authUser = selectedPithosAccount.authUser; + self.authToken = selectedPithosAccount.authToken; } } @@ -176,12 +218,33 @@ [self updateSync]; } +- (void)setSyncSkipHidden:(BOOL)aSyncSkipHidden { + syncSkipHidden = aSyncSkipHidden; + [self updateSync]; + [self selectedPithosAccountNodeChildrenUpdated:nil]; +} + - (void)setSyncDirectoryPath:(NSString *)aSyncDirectoryPath { - [syncDirectoryPath release]; syncDirectoryPath = [aSyncDirectoryPath copy]; [self updateSync]; } +- (void)setSyncAccountsDictionary:(NSMutableDictionary *)aSyncAccountsDictionary { + syncAccountsDictionary = [[NSMutableDictionary alloc] initWithCapacity:[aSyncAccountsDictionary count]]; + for (NSString *accountName in aSyncAccountsDictionary) { + NSDictionary *aSyncContainersDictionary = [aSyncAccountsDictionary objectForKey:accountName]; + NSMutableDictionary *syncContainersDictionary = [NSMutableDictionary dictionary]; + for (NSString *containerName in aSyncContainersDictionary) { + if (![accountName isEqualToString:@""] || ![[containerName lowercaseString] isEqualToString:@"shared to me"]) + [syncContainersDictionary setObject:[NSMutableSet setWithSet:[aSyncContainersDictionary objectForKey:containerName]] + forKey:containerName]; + } + if ([syncContainersDictionary count]) + [syncAccountsDictionary setObject:syncContainersDictionary forKey:accountName]; + } + [self updateSync]; +} + #pragma mark - #pragma Actions @@ -197,17 +260,16 @@ [self updateAccounts]; if (!accountRemoveEnable) return; - PithosAccount *removedPithosAccount = [selectedPithosAccount retain]; + PithosAccount *removedPithosAccount = selectedPithosAccount; pithos_macosAppDelegate *delegate = (pithos_macosAppDelegate *)[[NSApplication sharedApplication] delegate]; if ([delegate.currentPithosAccount isEqualTo:removedPithosAccount] && [delegate.pithosBrowserController operationsPending]) { - NSAlert *alert = [[[NSAlert alloc] init] autorelease]; + NSAlert *alert = [[NSAlert alloc] init]; [alert setMessageText:@"Operations Pending"]; [alert setInformativeText:@"There are pending operations in the browser, do you want to remove the account and cancel them?"]; [alert addButtonWithTitle:@"OK"]; [alert addButtonWithTitle:@"Cancel"]; NSInteger choice = [alert runModal]; if (choice == NSAlertSecondButtonReturn) { - [removedPithosAccount release]; return; } } @@ -215,13 +277,13 @@ [delegate.pithosAccountsDictionary removeObjectForKey:removedPithosAccount.name]; [delegate removedPithosAccount:removedPithosAccount]; [delegate savePithosAccounts:self]; - [removedPithosAccount release]; [self updateAccounts]; } #pragma Login Actions - (IBAction)login:(id)sender { + self.syncAccountsRootFilesNodes = [NSMutableDictionary dictionary]; if (!manual) { [selectedPithosAccount loginWithServerURL:serverURL]; } else { @@ -239,23 +301,40 @@ } - (IBAction)loginCancel:(id)server { - self.serverURL = [[selectedPithosAccount.serverURL copy] autorelease]; - self.authUser = [[selectedPithosAccount.authUser copy] autorelease]; - self.authToken = [[selectedPithosAccount.authToken copy] autorelease]; + self.serverURL = selectedPithosAccount.serverURL; + self.authUser = selectedPithosAccount.authUser; + self.authToken = selectedPithosAccount.authToken; + self.manual = NO; } #pragma Sync Actions - (IBAction)syncApply:(id)sender { - [selectedPithosAccount updateSyncWithSyncActive:syncActive syncDirectoryPath:syncDirectoryPath]; + [selectedPithosAccount updateSyncWithSyncActive:syncActive + syncDirectoryPath:syncDirectoryPath + syncAccountsDictionary:syncAccountsDictionary + syncSkipHidden:syncSkipHidden]; [self updateSync]; pithos_macosAppDelegate *delegate = (pithos_macosAppDelegate *)[[NSApplication sharedApplication] delegate]; [delegate savePithosAccounts:self]; + [delegate sync]; } - (IBAction)syncCancel:(id)sender { self.syncActive = selectedPithosAccount.syncActive; - self.syncDirectoryPath = [[selectedPithosAccount.syncDirectoryPath copy] autorelease]; + self.syncDirectoryPath = selectedPithosAccount.syncDirectoryPath; + self.syncAccountsDictionary = selectedPithosAccount.syncAccountsDictionary; + self.syncAccountsRootFilesNodes = [NSMutableDictionary dictionary]; + self.syncSkipHidden = selectedPithosAccount.syncSkipHidden; +} + +- (IBAction)syncRefresh:(id)sender { + selectedPithosAccount.accountNode.forcedRefresh = YES; + [selectedPithosAccount.accountNode invalidateChildrenRecursive]; + selectedPithosAccount.sharingAccountsNode.forcedRefresh = YES; + [selectedPithosAccount.sharingAccountsNode invalidateChildrenRecursive]; + if (selectedPithosAccount.accountNode.children && selectedPithosAccount.sharingAccountsNode.children) { + } } #pragma mark Groups Actions @@ -271,4 +350,370 @@ [selectedPithosAccount.accountNode refreshInfo]; } +#pragma mark - +#pragma mark NSOutlineViewDataSource + +// [PithosEmptyNode] +// - + [PithosContainerNode] +// -- + [PithosSubdirNode] +// -- [PithosEmptyNode] +// + [PithosSharingAccountNode] +// - + [PithosContainerNode] +// -- + [PithosSubdirNode] +// -- [PithosEmptyNode] + +- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item { + if (!selectedPithosAccount.active) + return 0; + if (outlineView == syncAccountsOutlineView) { + if (item == nil) { + // root: + # + NSInteger accountsCount = 0; + if ([selectedPithosAccount.accountNode.children count]) + accountsCount = 1; + if (selectedPithosAccount.sharingAccountsNode.children) + accountsCount += selectedPithosAccount.sharingAccountsNode.children.count; + return accountsCount; + } else if (item == syncAccountsMyAccountNode) { + // root/: # + if (selectedPithosAccount.accountNode.children) { + NSInteger containersCount = 0; + for (PithosContainerNode *node in selectedPithosAccount.accountNode.children) { + if (![[node.displayName lowercaseString] isEqualToString:@"shared to me"]) + containersCount++; + } + return containersCount; + } + } else if ([item class] == [PithosAccountNode class]) { + // root/: # + PithosAccountNode *accountNode = (PithosAccountNode *)item; + if (accountNode.children) + return accountNode.children.count; + } else if ([item class] == [PithosContainerNode class]) { + // root/{, }/: # + + PithosContainerNode *containerNode = (PithosContainerNode *)item; + if (containerNode.children) { + // We add 1 for the root files node + NSInteger subdirCount = 1; + for (PithosNode *node in containerNode.children) { + if (([node class] == [PithosSubdirNode class]) && (!syncSkipHidden || ![node.displayName hasPrefix:@"."])) + subdirCount++; + } + return subdirCount; + } + } + } + return 0; +} + +- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item { + if (outlineView == syncAccountsOutlineView) { + if (item == nil) { + // root: [ , + ] + if ([selectedPithosAccount.accountNode.children count]) { + if (index == 0) + return syncAccountsMyAccountNode; + else + return [selectedPithosAccount.sharingAccountsNode.children objectAtIndex:(index - 1)]; + } else { + return [selectedPithosAccount.sharingAccountsNode.children objectAtIndex:index]; + } + } else if (item == syncAccountsMyAccountNode) { + // root/: [ + ] + NSInteger currentContainerIndex = -1; + for (PithosContainerNode *node in selectedPithosAccount.accountNode.children) { + if (![[node.displayName lowercaseString] isEqualToString:@"shared to me"]) { + currentContainerIndex++; + if (currentContainerIndex == index) + return node; + } + } + } else if ([item class] == [PithosAccountNode class]) { + // root/: [ + ] + return [((PithosAccountNode *)item).children objectAtIndex:index]; + } else if ([item class] == [PithosContainerNode class]) { + // root/{, }/: [ +, ] + PithosContainerNode *containerNode = (PithosContainerNode *)item; + NSInteger currentSubdirIndex = -1; + for (PithosNode *node in containerNode.children) { + if (([node class] == [PithosSubdirNode class]) && (!syncSkipHidden || ![node.displayName hasPrefix:@"."])) { + currentSubdirIndex++; + if (currentSubdirIndex == index) + return node; + } + } + if (++currentSubdirIndex == index) { + NSString *accountName = containerNode.sharingAccount; + if (!accountName) + accountName = @""; + PithosEmptyNode *rootFilesNode = [[syncAccountsRootFilesNodes objectForKey:accountName] + objectForKey:containerNode.displayName]; + if (!rootFilesNode) { + if (![syncAccountsRootFilesNodes objectForKey:accountName]) + [syncAccountsRootFilesNodes setObject:[NSMutableDictionary dictionary] forKey:accountName]; + rootFilesNode = [[PithosEmptyNode alloc] initWithDisplayName:@"" + icon:[[NSWorkspace sharedWorkspace] iconForFileType:@""]]; + rootFilesNode.parent = containerNode; + [[syncAccountsRootFilesNodes objectForKey:accountName] setObject:rootFilesNode forKey:containerNode.displayName]; + } + return rootFilesNode; + } + } + } + return nil; +} + +- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item { + if (outlineView == syncAccountsOutlineView) { + if ((item == syncAccountsMyAccountNode) || + ([item class] == [PithosAccountNode class]) || + ([item class] == [PithosContainerNode class])) + return YES; + } + return NO; +} + +- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item { + if (outlineView == syncAccountsOutlineView) { + if ([[tableColumn identifier] isEqualToString:@"sync"]) { + if (item == syncAccountsMyAccountNode) { + // root/ + // My account is + // off if not in dictionary + // mixed if in dictionary with exclusions + // on if in dictionary without exclusions + NSMutableDictionary *syncContainersDictionary = [syncAccountsDictionary objectForKey:@""]; + if (syncContainersDictionary) { + for (PithosContainerNode *node in selectedPithosAccount.accountNode.children) { + if (![[node.displayName lowercaseString] isEqualToString:@"shared to me"]) { + NSMutableSet *containerExcludedDirectories = [syncContainersDictionary objectForKey:node.displayName]; + if (!containerExcludedDirectories || [containerExcludedDirectories count]) + return [NSNumber numberWithUnsignedInteger:NSMixedState]; + } + } + return [NSNumber numberWithUnsignedInteger:NSOnState]; + } + return [NSNumber numberWithUnsignedInteger:NSOffState]; + } else if ([item class] == [PithosAccountNode class]) { + // root/ + // A sharing account is + // off if not in dictionary + // mixed if in dictionary with exclusions + // on if in dictionary without exclusions + PithosAccountNode *accountNode = (PithosAccountNode *)item; + NSMutableDictionary *syncContainersDictionary = [syncAccountsDictionary objectForKey:accountNode.displayName]; + if (syncContainersDictionary) { + for (PithosContainerNode *node in accountNode.children) { + NSMutableSet *containerExcludedDirectories = [syncContainersDictionary objectForKey:node.displayName]; + if (!containerExcludedDirectories || [containerExcludedDirectories count]) + return [NSNumber numberWithUnsignedInteger:NSMixedState]; + } + return [NSNumber numberWithUnsignedInteger:NSOnState]; + } + return [NSNumber numberWithUnsignedInteger:NSOffState]; + } else if ([item class] == [PithosContainerNode class]) { + // root/{, }/ + // A container is + // off if not in dictionary + // mixed if in dictionary with exclusions + // on if in dictionary without exclusions + PithosContainerNode *node = (PithosContainerNode *)item; + NSString *accountName = node.sharingAccount; + if (!accountName) + accountName = @""; + NSMutableSet *containerExcludedDirectories = [[syncAccountsDictionary objectForKey:accountName] + objectForKey:node.displayName]; + if (containerExcludedDirectories) { + if ([containerExcludedDirectories count]) + return [NSNumber numberWithUnsignedInteger:NSMixedState]; + else + return [NSNumber numberWithUnsignedInteger:NSOnState]; + } + return [NSNumber numberWithUnsignedInteger:NSOffState]; + } else if ([item class] == [PithosSubdirNode class]) { + // root/{, }// + // Directory is off if parent container not in dictionary or if excluded + // displayName should be localized and lowercased + PithosSubdirNode *node = (PithosSubdirNode *)item; + NSString *accountName = node.sharingAccount; + if (!accountName) + accountName = @""; + NSMutableSet *containerExcludedDirectories = [[syncAccountsDictionary objectForKey:accountName] + objectForKey:node.parent.displayName]; + if (!containerExcludedDirectories || + [containerExcludedDirectories + containsObject:[[node.displayName lowercaseString] stringByReplacingOccurrencesOfString:@"/" withString:@":"]]) + return [NSNumber numberWithUnsignedInteger:NSOffState]; + else + return [NSNumber numberWithUnsignedInteger:NSOnState]; + } else if ([item class] == [PithosEmptyNode class]) { + // root/{, }// + // Root files is off if parent container not in dictionary or if excluded + PithosEmptyNode *node = (PithosEmptyNode *)item; + NSString *accountName = node.parent.sharingAccount; + if (!accountName) + accountName = @""; + NSMutableSet *containerExcludedDirectories = [[syncAccountsDictionary objectForKey:accountName] + objectForKey:node.parent.displayName]; + if (!containerExcludedDirectories || [containerExcludedDirectories containsObject:@""]) + return [NSNumber numberWithUnsignedInteger:NSOffState]; + else + return [NSNumber numberWithUnsignedInteger:NSOnState]; + } + return [NSNumber numberWithUnsignedInteger:NSOffState]; + } else if ([[tableColumn identifier] isEqualToString:@"path"]) { + return (PithosNode *)item; + } + } + return nil; +} + +- (void)outlineView:(NSOutlineView *)outlineView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn byItem:(id)item { + if (outlineView == syncAccountsOutlineView) { + if ([[tableColumn identifier] isEqualToString:@"sync"]) { + NSCellStateValue newState = [object unsignedIntegerValue]; + if (item == syncAccountsMyAccountNode) { + // root/ + // If new state is + // mixed/on include my account with no exclusions + // off exclude my account + if ((newState == NSOnState) || (newState == NSMixedState)) { + NSMutableDictionary *syncContainersDictionary = [NSMutableDictionary dictionary]; + for (PithosContainerNode *node in selectedPithosAccount.accountNode.children) { + if (![[node.displayName lowercaseString] isEqualToString:@"shared to me"]) + [syncContainersDictionary setObject:[NSMutableSet set] forKey:node.displayName]; + } + [syncAccountsDictionary setObject:syncContainersDictionary forKey:@""]; + } else { + [syncAccountsDictionary removeObjectForKey:@""]; + } + [outlineView reloadItem:item reloadChildren:YES]; + } else if ([item class] == [PithosAccountNode class]) { + // root/ + // If new state is + // mixed/on include sharing account with no exclusions + // off exclude sharing account + PithosAccountNode *accountNode = (PithosAccountNode *)item; + if ((newState == NSOnState) || (newState == NSMixedState)) { + NSMutableDictionary *syncContainersDictionary = [NSMutableDictionary dictionary]; + for (PithosContainerNode *node in accountNode.children) { + [syncContainersDictionary setObject:[NSMutableSet set] forKey:node.displayName]; + } + [syncAccountsDictionary setObject:syncContainersDictionary forKey:accountNode.displayName]; + } else { + [syncAccountsDictionary removeObjectForKey:accountNode.displayName]; + } + [outlineView reloadItem:item reloadChildren:YES]; + } else if ([item class] == [PithosContainerNode class]) { + // root/{, }/ + // If new state is + // mixed/on include container with no excluded directories + // off exclude container + PithosContainerNode *node = (PithosContainerNode *)item; + NSString *accountName = node.sharingAccount; + PithosNode *accountNode = node.parent; + if (!accountName) { + accountName = @""; + accountNode = syncAccountsMyAccountNode; + } + NSMutableDictionary *syncContainersDictionary = [syncAccountsDictionary objectForKey:accountName]; + if ((newState == NSOnState) || (newState == NSMixedState)) { + if (!syncContainersDictionary) { + syncContainersDictionary = [NSMutableDictionary dictionary]; + [syncAccountsDictionary setObject:syncContainersDictionary forKey:accountName]; + } + [syncContainersDictionary setObject:[NSMutableSet set] forKey:node.displayName]; + } else if (syncContainersDictionary) { + [syncContainersDictionary removeObjectForKey:node.displayName]; + if (![syncContainersDictionary count]) + [syncAccountsDictionary removeObjectForKey:accountName]; + } + [outlineView reloadItem:accountNode reloadChildren:YES]; + } else if ([item class] == [PithosSubdirNode class]) { + // root/{, }// + // If new state is + // mixed/on include directory (if container not included, include and exclude all others) + // off exclude directory + PithosSubdirNode *node = (PithosSubdirNode *)item; + NSString *accountName = node.sharingAccount; + PithosNode *accountNode = node.parent.parent; + if (!accountName) { + accountName = @""; + accountNode = syncAccountsMyAccountNode; + } + NSMutableDictionary *syncContainersDictionary = [syncAccountsDictionary objectForKey:accountName]; + NSMutableSet *containerExcludedDirectories = [syncContainersDictionary objectForKey:node.parent.displayName]; + NSString *directoryName = [[node.displayName lowercaseString] stringByReplacingOccurrencesOfString:@"/" withString:@":"]; + if ((newState == NSOnState) || (newState == NSMixedState)) { + if (containerExcludedDirectories) { + [containerExcludedDirectories removeObject:directoryName]; + } else { + if (!syncContainersDictionary) { + syncContainersDictionary = [NSMutableDictionary dictionary]; + [syncAccountsDictionary setObject:syncContainersDictionary forKey:accountName]; + } + NSMutableSet *newContainerExcludeDirectories = [NSMutableSet setWithObject:@""]; + for (PithosNode *siblingNode in node.parent.children) { + if (([siblingNode class] == [PithosSubdirNode class]) && + (!syncSkipHidden || ![siblingNode.displayName hasPrefix:@"."])) { + NSString *siblingDirectoryName = [[siblingNode.displayName lowercaseString] + stringByReplacingOccurrencesOfString:@"/" withString:@":"]; + if (![siblingDirectoryName isEqualToString:directoryName] && + ![newContainerExcludeDirectories containsObject:siblingDirectoryName]) + [newContainerExcludeDirectories addObject:siblingDirectoryName]; + } + } + [syncContainersDictionary setObject:newContainerExcludeDirectories forKey:node.parent.displayName]; + } + } else if (syncContainersDictionary && + containerExcludedDirectories && + ![containerExcludedDirectories containsObject:directoryName]) { + [containerExcludedDirectories addObject:directoryName]; + } + [outlineView reloadItem:accountNode reloadChildren:YES]; + } else if ([item class] == [PithosEmptyNode class]) { + // If new state is + // mixed/on include root files (if container not included, include and exclude all others) + // off exclude root files + PithosEmptyNode *node = (PithosEmptyNode *)item; + NSString *accountName = node.parent.sharingAccount; + PithosNode *accountNode = node.parent.parent; + if (!accountName) { + accountName = @""; + accountNode = syncAccountsMyAccountNode; + } + NSMutableDictionary *syncContainersDictionary = [syncAccountsDictionary objectForKey:accountName]; + NSMutableSet *containerExcludedDirectories = [syncContainersDictionary objectForKey:node.parent.displayName]; + if ((newState == NSOnState) || (newState == NSMixedState)) { + if (containerExcludedDirectories) { + [containerExcludedDirectories removeObject:@""]; + } else { + if (!syncContainersDictionary) { + syncContainersDictionary = [NSMutableDictionary dictionary]; + [syncAccountsDictionary setObject:syncContainersDictionary forKey:accountName]; + } + NSMutableSet *newContainerExcludeDirectories = [NSMutableSet set]; + for (PithosNode *siblingNode in node.parent.children) { + if (([siblingNode class] == [PithosSubdirNode class]) && + (!syncSkipHidden || ![siblingNode.displayName hasPrefix:@"."])) { + NSString *siblingDirectoryName = [[siblingNode.displayName lowercaseString] + stringByReplacingOccurrencesOfString:@"/" withString:@":"]; + if (![newContainerExcludeDirectories containsObject:siblingDirectoryName]) + [newContainerExcludeDirectories addObject:siblingDirectoryName]; + } + } + [syncContainersDictionary setObject:newContainerExcludeDirectories forKey:node.parent.displayName]; + } + } else if (syncContainersDictionary && + containerExcludedDirectories && + ![containerExcludedDirectories containsObject:@""]) { + [containerExcludedDirectories addObject:@""]; + } + [outlineView reloadItem:accountNode reloadChildren:YES]; + } + [self updateSync]; + } + } +} + @end