#import "PithosContainerNode.h"
#import "PithosSubdirNode.h"
#import "PithosObjectNode.h"
+#import "PithosSharingAccountsNode.h"
#import "PithosEmptyNode.h"
#import "ImageAndTextCell.h"
#import "FileSystemBrowserCell.h"
@end
@implementation PithosBrowserController
-@synthesize outlineViewDataSourceArray, verticalSplitView, horizontalSplitView, leftTopView, leftBottomView,
- outlineView, browser;
+@synthesize verticalSplitView, horizontalSplitView, leftTopView, leftBottomView, outlineView, browser;
@synthesize draggedNodes, draggedParentNode;
@synthesize clipboardNodes, clipboardParentNode, clipboardCopy;
[draggedNodes release];
[browserMenu release];
[sharedPreviewController release];
- [outlineViewDataSourceArray release];
- [mySharedRootNode release];
+ [othersSharedNode release];
+ [mySharedNode release];
+ [sharedNode release];
+ [containersNodeChildren release];
+ [containersNode release];
[accountNode release];
[rootNode release];
[super dealloc];
- (void)resetContainers:(NSNotification *)notification {
rootNode = nil;
[browser loadColumnZero];
- self.outlineViewDataSourceArray = nil;
-
- // Create the outlineView tree
- // CONTAINERS
- NSTreeNode *containersTreeNode = [NSTreeNode treeNodeWithRepresentedObject:
- [[[PithosEmptyNode alloc] initWithDisplayName:@"CONTAINERS" icon:nil] autorelease]];
-
- // SHARED
- NSTreeNode *sharedTreeNode = [NSTreeNode treeNodeWithRepresentedObject:
- [[[PithosEmptyNode alloc] initWithDisplayName:@"SHARED" icon:nil] autorelease]];
- // SHARED/my shared
- [[sharedTreeNode mutableChildNodes] addObject:[NSTreeNode treeNodeWithRepresentedObject:mySharedRootNode]];
- // SHARED/others shared
- [[sharedTreeNode mutableChildNodes] addObject:
- [NSTreeNode treeNodeWithRepresentedObject:
- [[[PithosEmptyNode alloc] initWithDisplayName:@"others shared"
- icon:[[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kGroupIcon)]
- ] autorelease]]];
-
- self.outlineViewDataSourceArray = [NSMutableArray arrayWithObjects:containersTreeNode, sharedTreeNode, nil];
+ [containersNodeChildren removeAllObjects];
+ [outlineView reloadData];
// Expand the folder outline view
[outlineView expandItem:nil expandChildren:YES];
[super windowDidLoad];
accountNode = [[PithosAccountNode alloc] init];
- mySharedRootNode = [[PithosAccountNode alloc] init];
- mySharedRootNode.displayName = @"my shared";
- mySharedRootNode.shared = YES;
- mySharedRootNode.icon = [[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kUserIcon)];
+ containersNode = [[PithosEmptyNode alloc] initWithDisplayName:@"CONTAINERS" icon:nil];
+ containersNodeChildren = [[NSMutableArray alloc] init];
+ sharedNode = [[PithosEmptyNode alloc] initWithDisplayName:@"SHARED" icon:nil];
+ mySharedNode = [[PithosAccountNode alloc] init];
+ mySharedNode.displayName = @"my shared";
+ mySharedNode.shared = YES;
+ mySharedNode.icon = [[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kUserIcon)];
+ othersSharedNode = [[PithosSharingAccountsNode alloc] init];
+ othersSharedNode.displayName = @"others shared";
+ othersSharedNode.icon = [[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kGroupIcon)];
[[[outlineView tableColumns] objectAtIndex:0] setDataCell:[[[PithosOutlineViewCell alloc] init] autorelease]];
// Register for updates
+ // PithosContainerNode updates browser nodes
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(pithosNodeChildrenUpdated:)
name:@"PithosContainerNodeChildrenUpdated"
object:nil];
+ // PithosSubdirNode updates browser nodes
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(pithosNodeChildrenUpdated:)
name:@"PithosSubdirNodeChildrenUpdated"
object:nil];
+ // PithosAccountNode accountNode updates outlineView container nodes
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(pithosAccountNodeChildrenUpdated:)
name:@"PithosAccountNodeChildrenUpdated"
object:accountNode];
+ // PithosAccountNode other than accountNode updates nodes
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(pithosNodeChildrenUpdated:)
name:@"PithosAccountNodeChildrenUpdated"
- object:mySharedRootNode];
+ object:nil];
+ // PithosSharingAccountsNode othersSharedNode updates browser nodes
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(pithosNodeChildrenUpdated:)
+ name:@"PithosSharingAccountsNodeChildrenUpdated"
+ object:othersSharedNode];
+ // Updated authentication credentials reset containers in the outline view
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(resetContainers:)
name:@"PithosAuthenticationCredentialsUpdated"
object:nil];
+ // Request for browser refresh
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(pithosBrowserRefreshNeeded:)
+ name:@"PithosBrowserRefreshNeeeded"
+ object:nil];
}
#pragma mark -
-#pragma Observers
+#pragma mark Observers
- (void)pithosNodeChildrenUpdated:(NSNotification *)notification {
PithosNode *node = (PithosNode *)[notification object];
+ if (node == accountNode)
+ return;
NSLog(@"pithosNodeChildrenUpdated:%@", node.url);
NSInteger lastColumn = [browser lastColumn];
for (NSInteger column = lastColumn; column >= 0; column--) {
- (void)pithosAccountNodeChildrenUpdated:(NSNotification *)notification {
BOOL containerPithosFound = NO;
BOOL containerTrashFound = NO;
- NSMutableArray *containersTreeNodeChildren = [NSMutableArray array];
+ NSMutableIndexSet *removedContainersNodeChildren = [NSMutableIndexSet indexSet];
+ for (NSUInteger i = 0 ; i < [containersNodeChildren count] ; i++) {
+ if (![accountNode.children containsObject:[containersNodeChildren objectAtIndex:i]])
+ [removedContainersNodeChildren addIndex:i];
+ }
+ [containersNodeChildren removeObjectsAtIndexes:removedContainersNodeChildren];
for (PithosContainerNode *containerNode in accountNode.children) {
if ([containerNode.pithosContainer.name isEqualToString:@"pithos"]) {
- [containersTreeNodeChildren insertObject:[NSTreeNode treeNodeWithRepresentedObject:containerNode] atIndex:0];
+ if (![containersNodeChildren containsObject:containerNode])
+ [containersNodeChildren insertObject:containerNode atIndex:0];
containerPithosFound = YES;
} else if ([containerNode.pithosContainer.name isEqualToString:@"trash"]) {
NSUInteger insertIndex = 1;
if (!containerPithosFound)
insertIndex = 0;
- [containersTreeNodeChildren insertObject:[NSTreeNode treeNodeWithRepresentedObject:containerNode] atIndex:insertIndex];
+ if (![containersNodeChildren containsObject:containerNode])
+ [containersNodeChildren insertObject:containerNode atIndex:insertIndex];
containerTrashFound = YES;
- } else {
- [containersTreeNodeChildren addObject:[NSTreeNode treeNodeWithRepresentedObject:containerNode]];
+ } else if (![containersNodeChildren containsObject:containerNode]) {
+ [containersNodeChildren addObject:containerNode];
}
}
BOOL refreshAccountNode = NO;
refreshAccountNode = YES;
}
}
- if (refreshAccountNode) {
+
+ if (refreshAccountNode)
[accountNode refresh];
- } else {
- [[[outlineViewDataSourceArray objectAtIndex:0] mutableChildNodes] setArray:containersTreeNodeChildren];
- self.outlineViewDataSourceArray = outlineViewDataSourceArray;
-
- // Expand the folder outline view
- [outlineView expandItem:nil expandChildren:YES];
- [outlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:1] byExtendingSelection:NO];
-
- [self refresh:nil];
+
+ [outlineView reloadData];
+
+ // Expand the folder outline view
+ [outlineView expandItem:nil expandChildren:YES];
+
+ if ((rootNode == containersNode) || (rootNode == sharedNode)) {
+ rootNode = [containersNodeChildren objectAtIndex:0];
+ [browser loadColumnZero];
}
+
+ if (notification)
+ [self refresh:nil];
+}
+
+- (void)pithosBrowserRefreshNeeded:(NSNotification *)notification {
+ [self refresh:nil];
}
#pragma mark -
-#pragma Actions
+#pragma mark Actions
- (IBAction)refresh:(id)sender {
+ if (sender)
+ [accountNode refresh];
for (NSInteger column = [browser lastColumn]; column >= 0; column--) {
[(PithosNode *)[browser parentForItemsInColumn:column] invalidateChildren];
}
}
#pragma mark -
-#pragma NSBrowserDelegate
+#pragma mark NSBrowserDelegate
- (id)rootItemForBrowser:(NSBrowser *)browser {
return rootNode;
- (BOOL)browser:(NSBrowser *)browser shouldEditItem:(id)item {
PithosNode *node = (PithosNode *)item;
- if (node.shared || ([node class] == [PithosContainerNode class]))
+ if (node.shared || node.sharingAccount ||
+ ([node class] == [PithosContainerNode class]) || ([node class] == [PithosAccountNode class]))
return NO;
return YES;
}
NSArray *objectRequests = [PithosFileUtilities objectDataRequestsForSubdirWithContainerName:node.pithosContainer.name
objectName:node.pithosObject.name
toDirectory:[dropDestination path]
- checkIfExists:YES];
+ checkIfExists:YES
+ sharingAccount:node.sharingAccount];
if (objectRequests) {
for (ASIPithosObjectRequest *objectRequest in objectRequests) {
[names addObject:[objectRequest.userInfo valueForKey:@"fileName"]];
ASIPithosObjectRequest *objectRequest = [PithosFileUtilities objectDataRequestWithContainerName:node.pithosContainer.name
objectName:node.pithosObject.name
toDirectory:[dropDestination path]
- checkIfExists:YES];
+ checkIfExists:YES
+ sharingAccount:node.sharingAccount];
if (objectRequest) {
[names addObject:[objectRequest.userInfo valueForKey:@"fileName"]];
objectRequest.delegate = self;
*row = -1;
// Only allow dropping in folders
if (*column != -1) {
+ PithosNode *dropNode;
if (*row != -1) {
// Check if the node is not a folder and if so redirect to the parent item
- if ([[browser itemAtRow:*row inColumn:*column] class] != [PithosSubdirNode class])
+ dropNode = [browser itemAtRow:*row inColumn:*column];
+ if ([dropNode class] != [PithosSubdirNode class])
*row = -1;
}
- *dropOperation = NSBrowserDropOn;
- result = NSDragOperationCopy;
+ if (*row == -1)
+ dropNode = [browser parentForItemsInColumn:*column];
+
+ if (!dropNode.shared && !dropNode.sharingAccount) {
+ *dropOperation = NSBrowserDropOn;
+ result = NSDragOperationCopy;
+ }
}
} else if ([[[info draggingPasteboard] types] containsObject:NSFilesPromisePboardType]) {
// For a drop above, the drop is redirected to the parent item
if (*row == -1)
dropNode = [browser parentForItemsInColumn:*column];
- if (!dropNode.shared) {
+ if (!dropNode.shared && !dropNode.sharingAccount) {
if ([info draggingSourceOperationMask] & NSDragOperationMove) {
// NSDragOperationCopy | NSDragOperationMove -> NSDragOperationMove
if ((([dropNode class] == [PithosContainerNode class]) ||
objectName:node.pithosObject.name
destinationContainerName:containerName
destinationObjectName:destinationObjectName
- checkIfExists:YES];
+ checkIfExists:YES
+ sharingAccount:nil];
if (objectRequest) {
objectRequest.delegate = self;
objectRequest.didFinishSelector = @selector(copyFinished:);
objectName:node.pithosObject.name
destinationContainerName:containerName
destinationObjectName:destinationObjectName
- checkIfExists:YES];
+ checkIfExists:YES
+ sharingAccount:nil];
if (objectRequests) {
for (ASIPithosObjectRequest *objectRequest in objectRequests) {
objectRequest.delegate = self;
}
#pragma mark -
+#pragma mark NSOutlineViewDataSource
+
+- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
+ if (item == nil)
+ return 2;
+ if (item == containersNode)
+ return containersNodeChildren.count;
+ if (item == sharedNode)
+ return 2;
+ return 0;
+}
+
+- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item {
+ if (item == nil)
+ return (!index ? containersNode : sharedNode);
+ if (item == sharedNode)
+ return (!index ? mySharedNode : othersSharedNode);
+ return [containersNodeChildren objectAtIndex:index];
+}
+
+- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
+ if ((item == containersNode) || (item == sharedNode))
+ return YES;
+ return NO;
+}
+
+- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item {
+ PithosNode *node = (PithosNode *)item;
+ return node;
+}
+
+#pragma mark -
#pragma mark NSOutlineViewDelegate
- (BOOL)outlineView:outlineView shouldSelectItem:(id)item {
- return ([[item representedObject] isLeaf]);
+ if ((item == containersNode) || (item == sharedNode))
+ return NO;
+ return YES;
}
- (BOOL)outlineView:(NSOutlineView *)outlineView isGroupItem:(id)item {
- return (![[item representedObject] isLeaf]);
+ if ((item == containersNode) || (item == sharedNode))
+ return YES;
+ return NO;
}
- (void)outlineViewSelectionDidChange:(NSNotification *)notification {
- PithosNode *node = [[[outlineView itemAtRow:[outlineView selectedRow]] representedObject] representedObject];
+ PithosNode *node = (PithosNode *)[outlineView itemAtRow:[outlineView selectedRow]];
if (node) {
rootNode = node;
[browser loadColumnZero];
- [self refresh:nil];
+ [self refresh:nil];
}
}
} else {
menuNode = [browser itemAtIndexPath:[menuNodesIndexPaths objectAtIndex:0]];
}
- if ([menuNode class] == [PithosAccountNode class])
+ if (([menuNode class] == [PithosAccountNode class]) || ([menuNode class] == [PithosSharingAccountsNode class]))
return;
BOOL shared = menuNode.shared;
+ BOOL sharingAccount = (menuNode.sharingAccount != nil);
- if (!shared) {
+ if (!shared && !sharingAccount) {
// New Folder
menuItem = [[[NSMenuItem alloc] initWithTitle:@"New Folder" action:@selector(menuNewFolder:) keyEquivalent:@""] autorelease];
[menuItem setRepresentedObject:menuNode];
[menuItem setRepresentedObject:[NSArray arrayWithObject:menuNode]];
[menu addItem:menuItem];
- if (!shared) {
+ if (!shared && !sharingAccount) {
// Paste
if (clipboardNodes) {
NSUInteger clipboardNodesCount = [clipboardNodes count];
[menuNodes addObject:[browser itemAtIndexPath:clickedNodeIndexPath]];
}
NSUInteger menuNodesCount = [menuNodes count];
- BOOL shared = ((PithosNode *)[menuNodes objectAtIndex:0]).shared;
+ PithosNode *firstMenuNode = (PithosNode *)[menuNodes objectAtIndex:0];
+ BOOL shared = firstMenuNode.shared;
+ BOOL sharingAccount = (firstMenuNode.sharingAccount != nil);
- if (!shared) {
+ if (!shared && !sharingAccount) {
// Move to Trash (pithos container only)
// Delete
if ([rootNode class] == [PithosContainerNode class]) {
}
}
- // Get Info
- menuItem = [[[NSMenuItem alloc] initWithTitle:@"Get Info" action:@selector(menuGetInfo:) keyEquivalent:@""] autorelease];
- [menuItem setRepresentedObject:menuNodes];
- [menu addItem:menuItem];
+ if (!sharingAccount || ([firstMenuNode class] != [PithosAccountNode class])) {
+ // Get Info
+ menuItem = [[[NSMenuItem alloc] initWithTitle:@"Get Info" action:@selector(menuGetInfo:) keyEquivalent:@""] autorelease];
+ [menuItem setRepresentedObject:menuNodes];
+ [menu addItem:menuItem];
+
+ if ((!shared && !sharingAccount) || ([firstMenuNode class] != [PithosContainerNode class]))
+ [menu addItem:[NSMenuItem separatorItem]];
+ }
- if (!shared) {
+ if (!shared && !sharingAccount) {
// Cut
- [menu addItem:[NSMenuItem separatorItem]];
+
if (menuNodesCount == 1)
menuItemTitle = [NSString stringWithFormat:@"Cut \"%@\"", ((PithosNode *)[menuNodes objectAtIndex:0]).displayName];
else
menuItem = [[[NSMenuItem alloc] initWithTitle:menuItemTitle action:@selector(menuCut:) keyEquivalent:@""] autorelease];
[menuItem setRepresentedObject:menuNodes];
[menu addItem:menuItem];
+ }
+
+ if ((!shared && !sharingAccount) ||
+ (([firstMenuNode class] != [PithosContainerNode class]) && ([firstMenuNode class] != [PithosAccountNode class]))) {
// Copy
if (menuNodesCount == 1)
menuItemTitle = [NSString stringWithFormat:@"Copy \"%@\"", ((PithosNode *)[menuNodes objectAtIndex:0]).displayName];
menuItem = [[[NSMenuItem alloc] initWithTitle:menuItemTitle action:@selector(menuCopy:) keyEquivalent:@""] autorelease];
[menuItem setRepresentedObject:menuNodes];
[menu addItem:menuItem];
+ }
+
+ if (!shared && !sharingAccount) {
// Paste
if (menuNodesCount == 1) {
PithosNode *menuNode = [menuNodes objectAtIndex:0];
objectName:node.pithosObject.name
destinationContainerName:containerName
destinationObjectName:destinationObjectName
- checkIfExists:YES];
+ checkIfExists:YES
+ sharingAccount:node.sharingAccount];
if (objectRequest) {
objectRequest.delegate = self;
objectRequest.didFinishSelector = @selector(copyFinished:);
objectName:node.pithosObject.name
destinationContainerName:containerName
destinationObjectName:destinationObjectName
- checkIfExists:YES];
+ checkIfExists:YES
+ sharingAccount:node.sharingAccount];
if (objectRequests) {
for (ASIPithosObjectRequest *objectRequest in objectRequests) {
objectRequest.delegate = self;