From 20f54e18efae4bfe4b0b37142734ef9628d61346 Mon Sep 17 00:00:00 2001 From: Miltiadis Vasilakis Date: Tue, 27 Sep 2011 00:22:35 +0300 Subject: [PATCH 1/1] 'my shared' nodes can be copied. If a shared node has its sharing property changed from its info window, the browser is refreshed. Refresh button also refreshes account containers. Modified the left NSOutlineView to use PithosNode objects directly, instead through an NSTreeController. --- pithos-macos/PithosBrowserController.h | 11 +- pithos-macos/PithosBrowserController.m | 159 +++++++++++++++++++--------- pithos-macos/PithosBrowserController.xib | 169 +++++++++++++++++++----------- pithos-macos/PithosNode.h | 1 - pithos-macos/PithosNode.m | 6 -- pithos-macos/PithosObjectNode.m | 13 ++- pithos-macos/PithosSubdirNode.m | 18 ++-- 7 files changed, 241 insertions(+), 136 deletions(-) diff --git a/pithos-macos/PithosBrowserController.h b/pithos-macos/PithosBrowserController.h index 077a94e..facd1b3 100644 --- a/pithos-macos/PithosBrowserController.h +++ b/pithos-macos/PithosBrowserController.h @@ -38,13 +38,16 @@ #import @class PithosNode; @class PithosAccountNode; +@class PithosEmptyNode; @interface PithosBrowserController : NSWindowController { PithosNode *rootNode; PithosAccountNode *accountNode; - PithosAccountNode *mySharedRootNode; - - NSMutableArray *outlineViewDataSourceArray; + PithosEmptyNode *containersNode; + NSMutableArray *containersNodeChildren; + PithosEmptyNode *sharedNode; + PithosAccountNode *mySharedNode; + PithosEmptyNode *othersSharedNode; NSViewController *sharedPreviewController; @@ -65,8 +68,6 @@ BOOL clipboardCopy; } -@property (nonatomic, retain) NSMutableArray *outlineViewDataSourceArray; - @property (nonatomic, assign) IBOutlet NSSplitView *verticalSplitView; @property (nonatomic, assign) IBOutlet NSSplitView *horizontalSplitView; @property (nonatomic, assign) IBOutlet NSView *leftTopView; diff --git a/pithos-macos/PithosBrowserController.m b/pithos-macos/PithosBrowserController.m index f2cace6..832014e 100644 --- a/pithos-macos/PithosBrowserController.m +++ b/pithos-macos/PithosBrowserController.m @@ -99,8 +99,7 @@ @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; @@ -119,8 +118,11 @@ [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]; @@ -143,26 +145,7 @@ - (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]; + [outlineView reloadData]; // Expand the folder outline view [outlineView expandItem:nil expandChildren:YES]; @@ -176,10 +159,15 @@ [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 = [[PithosEmptyNode alloc] initWithDisplayName:@"others shared" + icon:[[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kGroupIcon)]]; [[[outlineView tableColumns] objectAtIndex:0] setDataCell:[[[PithosOutlineViewCell alloc] init] autorelease]]; @@ -199,15 +187,19 @@ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pithosNodeChildrenUpdated:) name:@"PithosAccountNodeChildrenUpdated" - object:mySharedRootNode]; + object:mySharedNode]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(resetContainers:) name:@"PithosAuthenticationCredentialsUpdated" object:nil]; + [[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]; @@ -224,19 +216,26 @@ - (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; @@ -260,24 +259,34 @@ 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]; } @@ -285,7 +294,7 @@ } #pragma mark - -#pragma NSBrowserDelegate +#pragma mark NSBrowserDelegate - (id)rootItemForBrowser:(NSBrowser *)browser { return rootNode; @@ -1061,22 +1070,58 @@ forDraggedRowsWithIndexes:(NSIndexSet *)rowIndexes inColumn:(NSInteger)column { } #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]; } } @@ -1151,6 +1196,7 @@ forDraggedRowsWithIndexes:(NSIndexSet *)rowIndexes inColumn:(NSInteger)column { NSUInteger menuNodesCount = [menuNodes count]; BOOL shared = ((PithosNode *)[menuNodes objectAtIndex:0]).shared; + if (!shared) { // Move to Trash (pithos container only) // Delete @@ -1172,9 +1218,12 @@ forDraggedRowsWithIndexes:(NSIndexSet *)rowIndexes inColumn:(NSInteger)column { [menuItem setRepresentedObject:menuNodes]; [menu addItem:menuItem]; + if (!shared || ([[menuNodes objectAtIndex:0] class] != [PithosContainerNode class])) + [menu addItem:[NSMenuItem separatorItem]]; + if (!shared) { // Cut - [menu addItem:[NSMenuItem separatorItem]]; + if (menuNodesCount == 1) menuItemTitle = [NSString stringWithFormat:@"Cut \"%@\"", ((PithosNode *)[menuNodes objectAtIndex:0]).displayName]; else @@ -1182,6 +1231,9 @@ forDraggedRowsWithIndexes:(NSIndexSet *)rowIndexes inColumn:(NSInteger)column { menuItem = [[[NSMenuItem alloc] initWithTitle:menuItemTitle action:@selector(menuCut:) keyEquivalent:@""] autorelease]; [menuItem setRepresentedObject:menuNodes]; [menu addItem:menuItem]; + } + + if (!shared || ([[menuNodes objectAtIndex:0] class] != [PithosContainerNode class])) { // Copy if (menuNodesCount == 1) menuItemTitle = [NSString stringWithFormat:@"Copy \"%@\"", ((PithosNode *)[menuNodes objectAtIndex:0]).displayName]; @@ -1190,6 +1242,9 @@ forDraggedRowsWithIndexes:(NSIndexSet *)rowIndexes inColumn:(NSInteger)column { menuItem = [[[NSMenuItem alloc] initWithTitle:menuItemTitle action:@selector(menuCopy:) keyEquivalent:@""] autorelease]; [menuItem setRepresentedObject:menuNodes]; [menu addItem:menuItem]; + } + + if (!shared) { // Paste if (menuNodesCount == 1) { PithosNode *menuNode = [menuNodes objectAtIndex:0]; diff --git a/pithos-macos/PithosBrowserController.xib b/pithos-macos/PithosBrowserController.xib index 9b84421..40d9b21 100755 --- a/pithos-macos/PithosBrowserController.xib +++ b/pithos-macos/PithosBrowserController.xib @@ -23,7 +23,6 @@ NSTextField NSToolbarSeparatorItem NSWindowTemplate - NSTreeController NSTextFieldCell NSButtonCell NSTableColumn @@ -342,6 +341,7 @@ 4352 {180, 313} + YES @@ -440,6 +440,7 @@ {180, 313} + @@ -450,6 +451,7 @@ -2147483392 {{224, 17}, {15, 102}} + _doScroller: @@ -460,6 +462,7 @@ -2147483392 {{-100, -100}, {144, 15}} + 1 @@ -469,6 +472,7 @@ {180, 313} + 528 @@ -479,6 +483,7 @@ {180, 313} + NSView @@ -493,6 +498,7 @@ {{7, 21}, {166, 12}} + 16648 100 @@ -502,6 +508,7 @@ 266 {{5, 6}, {170, 14}} + YES @@ -549,6 +556,7 @@ {{69, 38}, {42, 42}} + YES @@ -568,18 +576,21 @@ {{0, 314}, {180, 86}} + NSView {180, 400} + 2 {180, 400} + NSView @@ -593,6 +604,7 @@ 4370 {{-1, -1}, {511, 402}} + YES @@ -617,12 +629,14 @@ {{181, 0}, {509, 400}} + NSView {690, 400} + YES 2 @@ -630,6 +644,7 @@ {{7, 11}, {690, 400}} + {{0, 0}, {1280, 778}} @@ -639,20 +654,6 @@ YES - - - YES - representedObject.displayName - representedObject - - PithosNode - - YES - YES - YES - childNodes - isLeaf - @@ -714,42 +715,6 @@ 37 - - contentArray: outlineViewDataSourceArray - - - - - - contentArray: outlineViewDataSourceArray - contentArray - outlineViewDataSourceArray - 2 - - - 42 - - - - value: arrangedObjects.representedObject - - - - - - value: arrangedObjects.representedObject - value - arrangedObjects.representedObject - - NSConditionallySetsEditable - - - 2 - - - 46 - - verticalSplitView @@ -789,6 +754,14 @@ 174 + + + dataSource + + + + 175 + @@ -927,11 +900,6 @@ - 38 - - - - 113 @@ -1109,7 +1077,6 @@ 31.IBPluginDependency 32.IBPluginDependency 35.IBPluginDependency - 38.IBPluginDependency 39.IBPluginDependency 8.IBPluginDependency @@ -1152,7 +1119,6 @@ com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin com.apple.InterfaceBuilder.CocoaPlugin - com.apple.InterfaceBuilder.CocoaPlugin @@ -1167,9 +1133,92 @@ - 174 + 175 + + + + YES + + PithosBrowserController + NSWindowController + + refresh: + id + + + refresh: + + refresh: + id + + + + YES + + YES + browser + horizontalSplitView + leftBottomView + leftTopView + outlineView + verticalSplitView + + + YES + NSBrowser + NSSplitView + NSView + NSView + NSOutlineView + NSSplitView + + + + YES + + YES + browser + horizontalSplitView + leftBottomView + leftTopView + outlineView + verticalSplitView + + + YES + + browser + NSBrowser + + + horizontalSplitView + NSSplitView + + + leftBottomView + NSView + + + leftTopView + NSView + + + outlineView + NSOutlineView + + + verticalSplitView + NSSplitView + + + + + IBProjectSource + ./Classes/PithosBrowserController.h + + + - 0 IBCocoaFramework diff --git a/pithos-macos/PithosNode.h b/pithos-macos/PithosNode.h index 0720d48..fa2f9f7 100644 --- a/pithos-macos/PithosNode.h +++ b/pithos-macos/PithosNode.h @@ -79,7 +79,6 @@ - (void)invalidateChildren; - (void)invalidateChildrenRecursive; - (void)refresh; -- (void)refreshToRoot; - (void)showPithosNodeInfo:(id)sender; - (void)pithosNodeInfoWillClose:(id)sender; diff --git a/pithos-macos/PithosNode.m b/pithos-macos/PithosNode.m index e8cac8d..4ae40d9 100644 --- a/pithos-macos/PithosNode.m +++ b/pithos-macos/PithosNode.m @@ -94,12 +94,6 @@ self.children; } -- (void)refreshToRoot { - [self invalidateChildren]; - [self.parent refreshToRoot]; - self.children; -} - - (void)showPithosNodeInfo:(id)sender { // Abstract method } diff --git a/pithos-macos/PithosObjectNode.m b/pithos-macos/PithosObjectNode.m index e72b6f1..d396d4b 100644 --- a/pithos-macos/PithosObjectNode.m +++ b/pithos-macos/PithosObjectNode.m @@ -108,9 +108,9 @@ pithosObject = [aPithosObject retain]; } self.isPublic = (pithosObject.publicURI != nil); - // Refresh parent if the object is in my shared and is no longer shared + // Refresh browser if the object is in my shared and is no longer shared if (shared && !pithosObject.sharing) - [self.parent refreshToRoot]; + [[NSNotificationCenter defaultCenter] postNotificationName:@"PithosBrowserRefreshNeeeded" object:self]; } #pragma mark - @@ -121,14 +121,17 @@ NSLog(@"cached: %d", [request didUseCachedResponse]); if ([request isEqualTo:applyMetadataObjectRequest]) { + int responseStatusCode = applyMetadataObjectRequest.responseStatusCode; + if (responseStatusCode != 202) + [PithosFileUtilities unexpectedResponseStatusAlertWithRequest:applyMetadataObjectRequest]; @synchronized(self) { [applyMetadataObjectRequest release]; applyMetadataObjectRequest = nil; } - [self refreshInfo]; + if (responseStatusCode == 202) + [self refreshInfo]; } else if ([request isEqualTo:refreshMetadataObjectRequest]) { [[pithosNodeInfoController window] makeFirstResponder:nil]; - self.pithosObject = [refreshMetadataObjectRequest object]; @synchronized(self) { [refreshMetadataObjectRequest release]; @@ -165,7 +168,7 @@ contentEncoding:pithosObject.contentEncoding contentDisposition:pithosObject.contentDisposition manifest:pithosObject.manifest - sharing:pithosObject.sharing + sharing:(pithosObject.sharing ? pithosObject.sharing : @"") isPublic:(isPublic ? ASIPithosObjectRequestPublicTrue : ASIPithosObjectRequestPublicFalse) metadata:pithosObject.metadata update:NO] retain]; diff --git a/pithos-macos/PithosSubdirNode.m b/pithos-macos/PithosSubdirNode.m index 6f24b9f..d634daa 100644 --- a/pithos-macos/PithosSubdirNode.m +++ b/pithos-macos/PithosSubdirNode.m @@ -116,9 +116,10 @@ static NSImage *sharedIcon = nil; self.prefix = [NSString stringWithString:pithosObject.name]; } self.isPublic = (pithosObject.publicURI != nil); - // Refresh parent if the object is in my shared and is no longer shared - if (shared && !pithosObject.subdir && !pithosObject.sharing) - [self.parent refreshToRoot]; + // Refresh browser if the object is in my shared and is no longer shared + if (shared && !pithosObject.subdir && !pithosObject.sharing) { + [[NSNotificationCenter defaultCenter] postNotificationName:@"PithosBrowserRefreshNeeeded" object:self]; + } } #pragma mark - @@ -129,19 +130,22 @@ static NSImage *sharedIcon = nil; NSLog(@"cached: %d", [request didUseCachedResponse]); if ([request isEqualTo:applyMetadataObjectRequest]) { + int responseStatusCode = applyMetadataObjectRequest.responseStatusCode; + if ((responseStatusCode != 201) && (responseStatusCode != 202)) + [PithosFileUtilities unexpectedResponseStatusAlertWithRequest:applyMetadataObjectRequest]; @synchronized(self) { [applyMetadataObjectRequest release]; applyMetadataObjectRequest = nil; } - [self refreshInfo]; + if ((responseStatusCode == 201) || (responseStatusCode == 202)) + [self refreshInfo]; } else if ([request isEqualTo:refreshMetadataObjectRequest]) { [[pithosNodeInfoController window] makeFirstResponder:nil]; self.pithosObject = [refreshMetadataObjectRequest object]; if (refreshParent) { // Ask the parent for refresh for the case where an object was removed // It is done here so that it doesn't affect the info window refresh - [parent invalidateChildren]; - [parent children]; + [parent refresh]; refreshParent = NO; } @synchronized(self) { @@ -245,7 +249,7 @@ static NSImage *sharedIcon = nil; contentEncoding:pithosObject.contentEncoding contentDisposition:pithosObject.contentDisposition manifest:pithosObject.manifest - sharing:pithosObject.sharing + sharing:(pithosObject.sharing ? pithosObject.sharing : @"") isPublic:(isPublic ? ASIPithosObjectRequestPublicTrue : ASIPithosObjectRequestPublicFalse) metadata:pithosObject.metadata update:NO] retain]; -- 1.7.10.4