Revision e8dc9335 pithos-macos/PithosPreferencesController.m

b/pithos-macos/PithosPreferencesController.m
38 38
#import "PithosPreferencesController.h"
39 39
#import "PithosBrowserController.h"
40 40
#import "PithosAccountNode.h"
41
#import "PithosSharingAccountsNode.h"
41 42
#import "PithosContainerNode.h"
42 43
#import "PithosSubdirNode.h"
43 44
#import "PithosObjectNode.h"
......
69 70
@synthesize accountsArrayController;
70 71
@synthesize accountRemoveEnable;
71 72
@synthesize serverURL, authUser, authToken, manual, loginEnable, loginCancelEnable;
72
@synthesize syncActive, syncDirectoryPath, syncContainersDictionary, syncApplyEnable, syncCancelEnable, 
73
            syncContainersOutlineView, syncContainersRootFilesNodes;
73
@synthesize syncActive, syncDirectoryPath, syncAccountsDictionary, syncApplyEnable, syncCancelEnable, 
74
            syncAccountsOutlineView, syncAccountsRootFilesNodes;
74 75
@synthesize groupsDictionaryController, selectedGroupMembersDictionaryController;
75 76

  
76 77
#pragma mark -
......
90 91
//	// Select the first tab when the window is loaded for the first time.
91 92
//	[[window valueForKeyPath:@"toolbar"] setSelectedItemIdentifier:@"0"];
92 93
    
93
    [[[syncContainersOutlineView tableColumns] objectAtIndex:1] setDataCell:[[[PithosPreferencesSyncOutlineViewCell alloc] init] autorelease]];
94
    [[[syncAccountsOutlineView tableColumns] objectAtIndex:1] setDataCell:[[[PithosPreferencesSyncOutlineViewCell alloc] init] autorelease]];
95
    syncAccountsMyAccountNode = [[PithosEmptyNode alloc] initWithDisplayName:@"<my account>" 
96
                                                                        icon:[[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kUserIcon)]];
94 97
    
95 98
    [groupsDictionaryController setInitialKey:@"group"];
96 99
    [groupsDictionaryController setInitialValue:@"user"];
......
129 132
}
130 133

  
131 134
- (void)selectedPithosAccountNodeChildrenUpdated:(NSNotification *)notification {
132
    [syncContainersOutlineView reloadData];
133
    [syncContainersOutlineView expandItem:nil expandChildren:YES];
135
    [syncAccountsOutlineView reloadData];
136
    [syncAccountsOutlineView expandItem:nil expandChildren:YES];
134 137
}
135 138

  
136 139
#pragma mark -
......
155 158
                             (![selectedPithosAccount.syncDirectoryPath isEqualToString:syncDirectoryPath] && 
156 159
                              (![[NSFileManager defaultManager] fileExistsAtPath:syncDirectoryPath isDirectory:&isDirectory] || 
157 160
                               isDirectory)) ||
158
                             ![selectedPithosAccount.syncContainersDictionary isEqualToDictionary:syncContainersDictionary]));
161
                             ![selectedPithosAccount.syncAccountsDictionary isEqualToDictionary:syncAccountsDictionary]));
159 162
    self.syncCancelEnable = (selectedPithosAccount.active && 
160 163
                             ((selectedPithosAccount.syncActive != syncActive) || 
161 164
                              ![selectedPithosAccount.syncDirectoryPath isEqualToString:syncDirectoryPath] ||
162
                              ![selectedPithosAccount.syncContainersDictionary isEqualToDictionary:syncContainersDictionary]));
165
                              ![selectedPithosAccount.syncAccountsDictionary isEqualToDictionary:syncAccountsDictionary]));
163 166
}
164 167

  
165 168
#pragma mark -
......
168 171
- (void)setSelectedPithosAccount:(PithosAccount *)aSelectedPithosAccount {
169 172
    if (aSelectedPithosAccount && ![aSelectedPithosAccount isEqualTo:selectedPithosAccount]) {
170 173
        selectedPithosAccount.accountNode.childrenUpdatedNotificationName = nil;
174
        selectedPithosAccount.sharingAccountsNode.childrenUpdatedNotificationName = nil;
171 175
        [selectedPithosAccount release];
172 176
        selectedPithosAccount = [aSelectedPithosAccount retain];
173
        selectedPithosAccount.accountNode.childrenUpdatedNotificationName = [NSString stringWithString:@"SelectedPithosAccountNodeChildrenUpdated"];
177
        selectedPithosAccount.accountNode.childrenUpdatedNotificationName = @"SelectedPithosAccountNodeChildrenUpdated";
178
        selectedPithosAccount.sharingAccountsNode.childrenUpdatedNotificationName = @"SelectedPithosAccountNodeChildrenUpdated";
174 179
        
175 180
        [self updateAccounts];
176 181
        [self loginCancel:self];
......
221 226
    [self updateSync];
222 227
}
223 228

  
224
- (void)setSyncContainersDictionary:(NSMutableDictionary *)aSyncContainersDictionary {
225
    [syncContainersDictionary release];
226
    syncContainersDictionary = [[NSMutableDictionary alloc] initWithCapacity:[aSyncContainersDictionary count]];
227
    for (NSString *containerName in aSyncContainersDictionary) {
228
        [syncContainersDictionary setObject:[NSMutableArray arrayWithArray:[aSyncContainersDictionary objectForKey:containerName]] 
229
                                                                    forKey:containerName];
229
- (void)setSyncAccountsDictionary:(NSMutableDictionary *)aSyncAccountsDictionary {
230
    [syncAccountsDictionary release];
231
    syncAccountsDictionary = [[NSMutableDictionary alloc] initWithCapacity:[aSyncAccountsDictionary count]];
232
    for (NSString *accountName in aSyncAccountsDictionary) {
233
        NSDictionary *aSyncContainersDictionary = [aSyncAccountsDictionary objectForKey:accountName];
234
        NSMutableDictionary *syncContainersDictionary = [NSMutableDictionary dictionary];
235
        for (NSString *containerName in aSyncContainersDictionary) {
236
            [syncContainersDictionary setObject:[NSMutableArray arrayWithArray:[aSyncContainersDictionary objectForKey:containerName]] 
237
                                         forKey:containerName];
238
        }
239
        if ([syncContainersDictionary count])
240
            [syncAccountsDictionary setObject:syncContainersDictionary forKey:accountName];
230 241
    }
231 242
    [self updateSync];
232 243
}
......
298 309
- (IBAction)syncApply:(id)sender {
299 310
    [selectedPithosAccount updateSyncWithSyncActive:syncActive 
300 311
                                  syncDirectoryPath:syncDirectoryPath 
301
                           syncContainersDictionary:syncContainersDictionary];
312
                           syncAccountsDictionary:syncAccountsDictionary];
302 313
    [self updateSync];
303 314
    pithos_macosAppDelegate *delegate = (pithos_macosAppDelegate *)[[NSApplication sharedApplication] delegate];
304 315
    [delegate savePithosAccounts:self];
......
308 319
- (IBAction)syncCancel:(id)sender {
309 320
    self.syncActive = selectedPithosAccount.syncActive;
310 321
    self.syncDirectoryPath = selectedPithosAccount.syncDirectoryPath;
311
    self.syncContainersDictionary = selectedPithosAccount.syncContainersDictionary;
312
    self.syncContainersRootFilesNodes = [NSMutableDictionary dictionary];
322
    self.syncAccountsDictionary = selectedPithosAccount.syncAccountsDictionary;
323
    self.syncAccountsRootFilesNodes = [NSMutableDictionary dictionary];
313 324
    [self selectedPithosAccountNodeChildrenUpdated:nil];
314 325
}
315 326

  
316 327
- (IBAction)syncRefresh:(id)sender {
317 328
    selectedPithosAccount.accountNode.forcedRefresh = YES;
318 329
    [selectedPithosAccount.accountNode invalidateChildrenRecursive];
319
    if (selectedPithosAccount.accountNode.children) {
330
    selectedPithosAccount.sharingAccountsNode.forcedRefresh = YES;
331
    [selectedPithosAccount.sharingAccountsNode invalidateChildrenRecursive];
332
    if (selectedPithosAccount.accountNode.children && selectedPithosAccount.sharingAccountsNode.children) {
320 333
    }
321 334
}
322 335

  
......
336 349
#pragma mark -
337 350
#pragma mark NSOutlineViewDataSource
338 351

  
352
// <my account> [PithosEmptyNode]
353
// - <container>+ [PithosContainerNode]
354
// -- <subdir>+ [PithosSubdirNode]
355
// -- <root files> [PithosEmptyNode]
356
// <sharing account>+ [PithosSharingAccountNode]
357
// - <container>+ [PithosContainerNode]
358
// -- <subdir>+ [PithosSubdirNode]
359
// -- <root files> [PithosEmptyNode]
360

  
339 361
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
340 362
    if (!selectedPithosAccount.active)
341 363
        return 0;
342
    if (outlineView == syncContainersOutlineView) {
364
    if (outlineView == syncAccountsOutlineView) {
343 365
        if (item == nil) {
366
            // root: <my account> + #<sharing account>
367
            if (selectedPithosAccount.sharingAccountsNode.children)
368
                return (selectedPithosAccount.sharingAccountsNode.children.count + 1);
369
            else
370
                return 1;
371
        } else if (item == syncAccountsMyAccountNode) {
372
            // root/<my account>: #<container>
344 373
            if (selectedPithosAccount.accountNode.children)
345 374
                return selectedPithosAccount.accountNode.children.count;
375
        } else if ([item class] == [PithosAccountNode class]) {
376
            // root/<sharing account>: #<container>
377
            PithosAccountNode *accountNode = (PithosAccountNode *)item;
378
            if (accountNode.children)
379
                return accountNode.children.count;
346 380
        } else if ([item class] == [PithosContainerNode class]) {
347
            // We add 1 for the root files node
348
            NSInteger subdirCount = 1;
349
            for (PithosNode *node in [(PithosContainerNode *)item children]) {
350
                if ([node class] == [PithosSubdirNode class])
351
                    subdirCount++;
381
            // root/{<my account>, <sharing account>}/<container>: #<subdir> + <root files>
382
            PithosContainerNode *containerNode = (PithosContainerNode *)item;
383
            if (containerNode.children) {
384
                // We add 1 for the root files node
385
                NSInteger subdirCount = 1;
386
                for (PithosNode *node in containerNode.children) {
387
                    if ([node class] == [PithosSubdirNode class])
388
                        subdirCount++;
389
                }
390
                return subdirCount;
352 391
            }
353
            return subdirCount;
354 392
        }
355 393
    }
356 394
    return 0;
357 395
}
358 396

  
359 397
- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item {
360
    if (outlineView == syncContainersOutlineView) {
361
        if (item == nil)
398
    if (outlineView == syncAccountsOutlineView) {
399
        if (item == nil) {
400
            // root: [ <my account>, <sharing account>+ ]
401
            if (index == 0)
402
                return syncAccountsMyAccountNode;
403
            else
404
                return [selectedPithosAccount.sharingAccountsNode.children objectAtIndex:(index - 1)];
405
        } else if (item == syncAccountsMyAccountNode) {
406
            // root/<my account>: [ <container>+ ]
362 407
            return [selectedPithosAccount.accountNode.children objectAtIndex:index];
363
        if ([item class] == [PithosContainerNode class]) {
408
        } else if ([item class] == [PithosAccountNode class]) {
409
            // root/<sharing account>: [ <container>+ ]
410
            return [((PithosAccountNode *)item).children objectAtIndex:index];
411
        } else if ([item class] == [PithosContainerNode class]) {
412
            // root/{<my account>, <sharing account>}/<container>: [ <subdir>+, <root files> ]
364 413
            PithosContainerNode *containerNode = (PithosContainerNode *)item;
365 414
            NSInteger currentSubdirIndex = -1;
366 415
            for (PithosNode *node in containerNode.children) {
......
371 420
                }
372 421
            }
373 422
            if (++currentSubdirIndex == index) {
374
                PithosEmptyNode *rootFilesNode = [syncContainersRootFilesNodes objectForKey:containerNode.displayName];
423
                NSString *accountName = containerNode.sharingAccount;
424
                if (!accountName)
425
                    accountName = @"";
426
                PithosEmptyNode *rootFilesNode = [[syncAccountsRootFilesNodes objectForKey:accountName] 
427
                                                  objectForKey:containerNode.displayName];
375 428
                if (!rootFilesNode) {
429
                    if (![syncAccountsRootFilesNodes objectForKey:accountName])
430
                        [syncAccountsRootFilesNodes setObject:[NSMutableDictionary dictionary] forKey:accountName];
376 431
                    rootFilesNode = [[[PithosEmptyNode alloc] initWithDisplayName:@"<root files>" 
377 432
                                                                             icon:[[NSWorkspace sharedWorkspace] iconForFileType:@""]] 
378 433
                                     autorelease];
379 434
                    rootFilesNode.parent = containerNode;
380
                    [syncContainersRootFilesNodes setObject:rootFilesNode forKey:containerNode.displayName];
435
                    [[syncAccountsRootFilesNodes objectForKey:accountName] setObject:rootFilesNode forKey:containerNode.displayName];
381 436
                }
382 437
                return rootFilesNode;
383 438
            }
......
387 442
}
388 443

  
389 444
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
390
    if (outlineView == syncContainersOutlineView) {
391
        if ([item class] == [PithosContainerNode class])
445
    if (outlineView == syncAccountsOutlineView) {
446
        if ((item == syncAccountsMyAccountNode) || 
447
            ([item class] == [PithosAccountNode class]) || 
448
            ([item class] == [PithosContainerNode class]))
392 449
            return YES;
393 450
    }
394 451
    return NO;
395 452
}
396 453

  
397 454
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item {
398
    if (outlineView == syncContainersOutlineView) {
455
    if (outlineView == syncAccountsOutlineView) {
399 456
        if ([[tableColumn identifier] isEqualToString:@"sync"]) {
400
            if ([item class] == [PithosContainerNode class]) {
457
            if (item == syncAccountsMyAccountNode) {
458
                // root/<my account>
459
                // My account is 
460
                // off if not in dictionary
461
                // mixed if in dictionary with exclusions
462
                // on if in dictionary without exclusions
463
                NSMutableDictionary *syncContainersDictionary = [syncAccountsDictionary objectForKey:@""];
464
                if (syncContainersDictionary) {
465
                    for (PithosContainerNode *node in selectedPithosAccount.accountNode.children) {
466
                        NSMutableArray *containerExcludedDirectories = [syncContainersDictionary objectForKey:node.displayName];
467
                        if (!containerExcludedDirectories || [containerExcludedDirectories count])
468
                            return [NSNumber numberWithUnsignedInteger:NSMixedState];
469
                    }
470
                    return [NSNumber numberWithUnsignedInteger:NSOnState];
471
                }
472
                return [NSNumber numberWithUnsignedInteger:NSOffState];
473
            } else if ([item class] == [PithosAccountNode class]) {
474
                // root/<sharing account>
475
                // A sharing account is 
476
                // off if not in dictionary
477
                // mixed if in dictionary with exclusions
478
                // on if in dictionary without exclusions
479
                PithosAccountNode *accountNode = (PithosAccountNode *)item;
480
                NSMutableDictionary *syncContainersDictionary = [syncAccountsDictionary objectForKey:accountNode.displayName];
481
                if (syncContainersDictionary) {
482
                    for (PithosContainerNode *node in accountNode.children) {
483
                        NSMutableArray *containerExcludedDirectories = [syncContainersDictionary objectForKey:node.displayName];
484
                        if (!containerExcludedDirectories || [containerExcludedDirectories count])
485
                            return [NSNumber numberWithUnsignedInteger:NSMixedState];
486
                    }
487
                    return [NSNumber numberWithUnsignedInteger:NSOnState];
488
                }
489
                return [NSNumber numberWithUnsignedInteger:NSOffState];
490
            } else if ([item class] == [PithosContainerNode class]) {
491
                // root/{<my account>, <sharing account>}/<container>
401 492
                // A container is 
402 493
                // off if not in dictionary
403 494
                // mixed if in dictionary with exclusions
404 495
                // on if in dictionary without exclusions
405 496
                PithosContainerNode *node = (PithosContainerNode *)item;
406
                NSMutableArray *containerExcludedDirectories = [syncContainersDictionary objectForKey:node.displayName];
497
                NSString *accountName = node.sharingAccount;
498
                if (!accountName)
499
                    accountName = @"";
500
                NSMutableArray *containerExcludedDirectories = [[syncAccountsDictionary objectForKey:accountName] 
501
                                                                objectForKey:node.displayName];
407 502
                if (containerExcludedDirectories) {
408 503
                    if ([containerExcludedDirectories count])
409 504
                        return [NSNumber numberWithUnsignedInteger:NSMixedState];
......
412 507
                }
413 508
                return [NSNumber numberWithUnsignedInteger:NSOffState];
414 509
            } else if ([item class] == [PithosSubdirNode class]) {
415
                // Root files are off if parent container not in dictionary or if excluded
510
                // root/{<my account>, <sharing account>}/<container>/<subdir>
511
                // Directory is off if parent container not in dictionary or if excluded
416 512
                // displayName should be localized and lowercased
417 513
                PithosSubdirNode *node = (PithosSubdirNode *)item;
418
                NSMutableArray *containerExcludedDirectories = [syncContainersDictionary objectForKey:node.parent.displayName];
419
                NSString *directoryName = [[node.displayName lowercaseString] stringByReplacingOccurrencesOfString:@"/" withString:@":"];
420
                if (!containerExcludedDirectories || [containerExcludedDirectories containsObject:directoryName])
514
                NSString *accountName = node.sharingAccount;
515
                if (!accountName)
516
                    accountName = @"";
517
                NSMutableArray *containerExcludedDirectories = [[syncAccountsDictionary objectForKey:accountName] 
518
                                                                objectForKey:node.parent.displayName];
519
                if (!containerExcludedDirectories || 
520
                    [containerExcludedDirectories 
521
                     containsObject:[[node.displayName lowercaseString] stringByReplacingOccurrencesOfString:@"/" withString:@":"]])
421 522
                    return [NSNumber numberWithUnsignedInteger:NSOffState];
422 523
                else
423 524
                    return [NSNumber numberWithUnsignedInteger:NSOnState];
424 525
            } else if ([item class] == [PithosEmptyNode class]) {
425
                // Root files are off if parent container not in dictionary or if excluded
526
                // root/{<my account>, <sharing account>}/<container>/<root files>
527
                // Root files is off if parent container not in dictionary or if excluded
426 528
                PithosEmptyNode *node = (PithosEmptyNode *)item;
427
                NSMutableArray *containerExcludedDirectories = [syncContainersDictionary objectForKey:node.parent.displayName];
529
                NSString *accountName = node.parent.sharingAccount;
530
                if (!accountName)
531
                    accountName = @"";
532
                NSMutableArray *containerExcludedDirectories = [[syncAccountsDictionary objectForKey:accountName] 
533
                                                                objectForKey:node.parent.displayName];
428 534
                if (!containerExcludedDirectories || [containerExcludedDirectories containsObject:@""])
429 535
                    return [NSNumber numberWithUnsignedInteger:NSOffState];
430 536
                else
......
439 545
}
440 546

  
441 547
- (void)outlineView:(NSOutlineView *)outlineView setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn byItem:(id)item {
442
    if (outlineView == syncContainersOutlineView) {
548
    if (outlineView == syncAccountsOutlineView) {
443 549
        if ([[tableColumn identifier] isEqualToString:@"sync"]) {
444 550
            NSCellStateValue newState = [object unsignedIntegerValue];
445
            if ([item class] == [PithosContainerNode class]) {
551
            if (item == syncAccountsMyAccountNode) {
552
                // root/<my account>
553
                // If new state is
554
                // mixed/on include my account with no exclusions
555
                // off exclude my account
556
                if ((newState == NSOnState) || (newState == NSMixedState)) {
557
                    NSMutableDictionary *syncContainersDictionary = [NSMutableDictionary dictionary];
558
                    for (PithosContainerNode *node in selectedPithosAccount.accountNode.children) {
559
                        [syncContainersDictionary setObject:[NSMutableArray array] forKey:node.displayName];
560
                    }
561
                    [syncAccountsDictionary setObject:syncContainersDictionary forKey:@""];
562
                } else {
563
                    [syncAccountsDictionary removeObjectForKey:@""];
564
                }
565
                [outlineView reloadItem:item reloadChildren:YES];
566
            } else if ([item class] == [PithosAccountNode class]) {
567
                // root/<sharing account>
568
                // If new state is
569
                // mixed/on include sharing account with no exclusions
570
                // off exclude sharing account
571
                PithosAccountNode *accountNode = (PithosAccountNode *)item;
572
                if ((newState == NSOnState) || (newState == NSMixedState)) {
573
                    NSMutableDictionary *syncContainersDictionary = [NSMutableDictionary dictionary];
574
                    for (PithosContainerNode *node in accountNode.children) {
575
                        [syncContainersDictionary setObject:[NSMutableArray array] forKey:node.displayName];
576
                    }
577
                    [syncAccountsDictionary setObject:syncContainersDictionary forKey:accountNode.displayName];
578
                } else {
579
                    [syncAccountsDictionary removeObjectForKey:accountNode.displayName];
580
                }
581
                [outlineView reloadItem:item reloadChildren:YES];
582
            } else if ([item class] == [PithosContainerNode class]) {
583
                // root/{<my account>, <sharing account>}/<container>
446 584
                // If new state is
447 585
                // mixed/on include container with no excluded directories
448 586
                // off exclude container
449 587
                PithosContainerNode *node = (PithosContainerNode *)item;
588
                NSString *accountName = node.sharingAccount;
589
                PithosNode *accountNode = node.parent;
590
                if (!accountName) {
591
                    accountName = @"";
592
                    accountNode = syncAccountsMyAccountNode;
593
                }
594
                NSMutableDictionary *syncContainersDictionary = [syncAccountsDictionary objectForKey:accountName];
450 595
                if ((newState == NSOnState) || (newState == NSMixedState)) {
596
                    if (!syncContainersDictionary) {
597
                        syncContainersDictionary = [NSMutableDictionary dictionary];
598
                        [syncAccountsDictionary setObject:syncContainersDictionary forKey:accountName];
599
                    }
451 600
                    [syncContainersDictionary setObject:[NSMutableArray array] forKey:node.displayName];
452
                } else {
601
                } else if (syncContainersDictionary) {
453 602
                    [syncContainersDictionary removeObjectForKey:node.displayName];
603
                    if (![syncContainersDictionary count])
604
                        [syncAccountsDictionary removeObjectForKey:accountName];
454 605
                }
455
                [outlineView reloadItem:item reloadChildren:YES];
606
                [outlineView reloadItem:accountNode reloadChildren:YES];
456 607
            } else if ([item class] == [PithosSubdirNode class]) {
608
                // root/{<my account>, <sharing account>}/<container>/<subdir>
457 609
                // If new state is
458 610
                // mixed/on include directory (if container not included, include and exclude all others)
459 611
                // off exclude directory
460 612
                PithosSubdirNode *node = (PithosSubdirNode *)item;
613
                NSString *accountName = node.sharingAccount;
614
                PithosNode *accountNode = node.parent.parent;
615
                if (!accountName) {
616
                    accountName = @"";
617
                    accountNode = syncAccountsMyAccountNode;
618
                }
619
                NSMutableDictionary *syncContainersDictionary = [syncAccountsDictionary objectForKey:accountName];
461 620
                NSMutableArray *containerExcludedDirectories = [syncContainersDictionary objectForKey:node.parent.displayName];
462 621
                NSString *directoryName = [[node.displayName lowercaseString] stringByReplacingOccurrencesOfString:@"/" withString:@":"];
463 622
                if ((newState == NSOnState) || (newState == NSMixedState)) {
464 623
                    if (containerExcludedDirectories) {
465 624
                        [containerExcludedDirectories removeObject:directoryName];
466 625
                    } else {
626
                        if (!syncContainersDictionary) {
627
                            syncContainersDictionary = [NSMutableDictionary dictionary];
628
                            [syncAccountsDictionary setObject:syncContainersDictionary forKey:accountName];
629
                        }
467 630
                        NSMutableArray *newContainerExcludeDirectories = [NSMutableArray arrayWithObject:@""];
468 631
                        for (PithosNode *siblingNode in node.parent.children) {
469 632
                            if ([siblingNode class] == [PithosSubdirNode class]) {
470
                                NSString *siblingDirectoryName = [[siblingNode.displayName lowercaseString] stringByReplacingOccurrencesOfString:@"/" withString:@":"];
633
                                NSString *siblingDirectoryName = [[siblingNode.displayName lowercaseString] 
634
                                                                  stringByReplacingOccurrencesOfString:@"/" withString:@":"];
471 635
                                if (![siblingDirectoryName isEqualToString:directoryName] && 
472 636
                                    ![newContainerExcludeDirectories containsObject:siblingDirectoryName])
473 637
                                    [newContainerExcludeDirectories addObject:siblingDirectoryName];
......
475 639
                        }
476 640
                        [syncContainersDictionary setObject:newContainerExcludeDirectories forKey:node.parent.displayName];
477 641
                    }
478
                } else if (![containerExcludedDirectories containsObject:directoryName]) {
642
                } else if (syncContainersDictionary && 
643
                           containerExcludedDirectories && 
644
                           ![containerExcludedDirectories containsObject:directoryName]) {
479 645
                    [containerExcludedDirectories addObject:directoryName];
480 646
                }
481
                [outlineView reloadItem:[outlineView parentForItem:item]];
647
                [outlineView reloadItem:accountNode reloadChildren:YES];
482 648
            } else if ([item class] == [PithosEmptyNode class]) {
483 649
                // If new state is
484 650
                // mixed/on include root files (if container not included, include and exclude all others)
485 651
                // off exclude root files
486 652
                PithosEmptyNode *node = (PithosEmptyNode *)item;
653
                NSString *accountName = node.parent.sharingAccount;
654
                PithosNode *accountNode = node.parent.parent;
655
                if (!accountName) {
656
                    accountName = @"";
657
                    accountNode = syncAccountsMyAccountNode;
658
                }
659
                NSMutableDictionary *syncContainersDictionary = [syncAccountsDictionary objectForKey:accountName];
487 660
                NSMutableArray *containerExcludedDirectories = [syncContainersDictionary objectForKey:node.parent.displayName];
488 661
                if ((newState == NSOnState) || (newState == NSMixedState)) {
489 662
                    if (containerExcludedDirectories) {
490 663
                        [containerExcludedDirectories removeObject:@""];
491 664
                    } else {
665
                        if (!syncContainersDictionary) {
666
                            syncContainersDictionary = [NSMutableDictionary dictionary];
667
                            [syncAccountsDictionary setObject:syncContainersDictionary forKey:accountName];
668
                        }
492 669
                        NSMutableArray *newContainerExcludeDirectories = [NSMutableArray array];
493 670
                        for (PithosNode *siblingNode in node.parent.children) {
494 671
                            if ([siblingNode class] == [PithosSubdirNode class]) {
495
                                NSString *siblingDirectoryName = [[siblingNode.displayName lowercaseString] stringByReplacingOccurrencesOfString:@"/" withString:@":"];
672
                                NSString *siblingDirectoryName = [[siblingNode.displayName lowercaseString] 
673
                                                                  stringByReplacingOccurrencesOfString:@"/" withString:@":"];
496 674
                                if (![newContainerExcludeDirectories containsObject:siblingDirectoryName])
497 675
                                    [newContainerExcludeDirectories addObject:siblingDirectoryName];
498 676
                            }
499 677
                        }
500 678
                        [syncContainersDictionary setObject:newContainerExcludeDirectories forKey:node.parent.displayName];
501 679
                    }
502
                } else if (![containerExcludedDirectories containsObject:@""]) {
680
                } else if (syncContainersDictionary && 
681
                           containerExcludedDirectories && 
682
                           ![containerExcludedDirectories containsObject:@""]) {
503 683
                    [containerExcludedDirectories addObject:@""];
504 684
                }
505
                [outlineView reloadItem:[outlineView parentForItem:item]];
685
                [outlineView reloadItem:accountNode reloadChildren:YES];
506 686
            }
507 687
            [self updateSync];
508 688
        }

Also available in: Unified diff