New folder menu item.
authorMiltiadis Vasilakis <mvasilak@gmail.com>
Mon, 19 Sep 2011 22:42:43 +0000 (01:42 +0300)
committerMiltiadis Vasilakis <mvasilak@gmail.com>
Mon, 19 Sep 2011 22:42:43 +0000 (01:42 +0300)
Other fixes and improvements.

pithos-macos/PithosBrowserController.m
pithos-macos/PithosFileUtilities.m

index 5d86b74..d3d5d42 100644 (file)
@@ -367,19 +367,22 @@ forDraggedRowsWithIndexes:(NSIndexSet *)rowIndexes inColumn:(NSInteger)column {
             [alert addButtonWithTitle:@"Cancel"];
             NSInteger choice = [alert runModal];
             if (choice == NSAlertFirstButtonReturn) {
-                NSArray *objectRequests = [PithosFileUtilities objectDataRequestsForSubdirWithContainerName:node.pithosContainer.name 
-                                                                                                 objectName:node.pithosObject.name 
-                                                                                                toDirectory:[dropDestination path] 
-                                                                                              checkIfExists:YES];
-                if (objectRequests) {
-                    for (ASIPithosObjectRequest *objectRequest in objectRequests) {
-                        [names addObject:[objectRequest.userInfo valueForKey:@"fileName"]];
-                        objectRequest.delegate = self;
-                        objectRequest.didFinishSelector = @selector(downloadObjectFinished:);
-                        objectRequest.didFailSelector = @selector(downloadObjectFailed:);
-                        [objectRequest startAsynchronous];
+                dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
+                dispatch_async(queue, ^{
+                    NSArray *objectRequests = [PithosFileUtilities objectDataRequestsForSubdirWithContainerName:node.pithosContainer.name 
+                                                                                                     objectName:node.pithosObject.name 
+                                                                                                    toDirectory:[dropDestination path] 
+                                                                                                  checkIfExists:YES];
+                    if (objectRequests) {
+                        for (ASIPithosObjectRequest *objectRequest in objectRequests) {
+                            [names addObject:[objectRequest.userInfo valueForKey:@"fileName"]];
+                            objectRequest.delegate = self;
+                            objectRequest.didFinishSelector = @selector(downloadObjectFinished:);
+                            objectRequest.didFailSelector = @selector(downloadObjectFailed:);
+                            [objectRequest startAsynchronous];
+                        }
                     }
-                }
+                });
             }
         } else {
             ASIPithosObjectRequest *objectRequest = [PithosFileUtilities objectDataRequestWithContainerName:node.pithosContainer.name 
@@ -566,7 +569,7 @@ forDraggedRowsWithIndexes:(NSIndexSet *)rowIndexes inColumn:(NSInteger)column {
 - (void)downloadObjectFinished:(ASIPithosObjectRequest *)objectRequest {
     NSLog(@"Download completed: %@", [objectRequest url]);
     if (objectRequest.responseStatusCode == 200) {
-        if ([objectRequest contentLength] == 0) {
+        if (([objectRequest contentLength] == 0) && (![[objectRequest contentType] isEqualToString:@"application/directory"])) {
             NSLog(@"Downloaded  0 bytes");
             NSFileManager *defaultManager = [NSFileManager defaultManager];
             NSString *filePath = [objectRequest.userInfo objectForKey:@"filePath"];
@@ -751,28 +754,56 @@ forDraggedRowsWithIndexes:(NSIndexSet *)rowIndexes inColumn:(NSInteger)column {
     NSMenuItem *menuItem;
     if ((column == -1) || (row == -1)) {
         // General context menu
+        NSArray *menuNodesIndexPaths = [browser selectionIndexPaths];
+        PithosNode *menuNode;
+        if ([menuNodesIndexPaths count] == 0) {
+            menuNode = [browser parentForItemsInColumn:0];
+        } else if (([menuNodesIndexPaths count] != 1) || 
+            ([[browser itemAtIndexPath:[menuNodesIndexPaths objectAtIndex:0]] class] == [PithosObjectNode class])) {
+            menuNode = [browser parentForItemsInColumn:([[menuNodesIndexPaths objectAtIndex:0] length] - 1)];
+        } else {
+            menuNode = [browser itemAtIndexPath:[menuNodesIndexPaths objectAtIndex:0]];
+        }
+        NSArray *menuNodes = [NSArray arrayWithObject:menuNode];
+        // New Folder
+        menuItem = [[[NSMenuItem alloc] initWithTitle:@"New Folder" action:@selector(newFolder:) keyEquivalent:@""] autorelease];
+        [menuItem setRepresentedObject:menuNodes];
+        [menu addItem:menuItem];
+        if ([menuNode class] == [PithosSubdirNode class]) {
+            [menu addItem:[NSMenuItem separatorItem]];
+            // Get Info
+            menuItem = [[[NSMenuItem alloc] initWithTitle:@"Get Info" action:@selector(getInfo:) keyEquivalent:@""] autorelease];
+            [menuItem setRepresentedObject:menuNodes];
+            [menu addItem:menuItem];
+        }
     } else {
+        // Node context menu
         NSIndexPath *clickedNodeIndexPath = [[browser indexPathForColumn:column] indexPathByAddingIndex:row];
         NSArray *menuNodesIndexPaths = [browser selectionIndexPaths];
-        if (![menuNodesIndexPaths containsObject:clickedNodeIndexPath])
-            menuNodesIndexPaths = [NSArray arrayWithObject:clickedNodeIndexPath];
-        
+        NSMutableArray *menuNodes = [NSMutableArray arrayWithCapacity:[menuNodesIndexPaths count]];
+        if ([menuNodesIndexPaths containsObject:clickedNodeIndexPath]) {
+            for (NSIndexPath *nodeIndexPath in menuNodesIndexPaths) {
+                [menuNodes addObject:[browser itemAtIndexPath:nodeIndexPath]];
+            }
+        } else {
+            [menuNodes addObject:[browser itemAtIndexPath:clickedNodeIndexPath]];
+        }
         // Move to Trash (pithos container only)
         // Delete
         if ([rootNode class] == [PithosContainerNode class]) {
             if ([rootNode.pithosContainer.name isEqualToString:@"pithos"]) {
                 menuItem = [[[NSMenuItem alloc] initWithTitle:@"Move to Trash" action:@selector(moveToTrash:) keyEquivalent:@""] autorelease];
-                [menuItem setRepresentedObject:menuNodesIndexPaths];
+                [menuItem setRepresentedObject:menuNodes];
                 [menu addItem:menuItem];
             }
             menuItem = [[[NSMenuItem alloc] initWithTitle:@"Delete" action:@selector(deleteObject:) keyEquivalent:@""] autorelease];
-            [menuItem setRepresentedObject:menuNodesIndexPaths];
+            [menuItem setRepresentedObject:menuNodes];
             [menu addItem:menuItem];
             [menu addItem:[NSMenuItem separatorItem]];
         }
         // Get Info
         menuItem = [[[NSMenuItem alloc] initWithTitle:@"Get Info" action:@selector(getInfo:) keyEquivalent:@""] autorelease];
-        [menuItem setRepresentedObject:menuNodesIndexPaths];
+        [menuItem setRepresentedObject:menuNodes];
         [menu addItem:menuItem];
     }
 }
@@ -780,16 +811,70 @@ forDraggedRowsWithIndexes:(NSIndexSet *)rowIndexes inColumn:(NSInteger)column {
 #pragma mark -
 #pragma mark Menu Actions
 
+- (void)newFolder:(NSMenuItem *)sender {
+    for (PithosNode *node in ((NSArray *)[sender representedObject])) {
+        if ([node class] == [PithosContainerNode class]) {
+            dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
+            dispatch_async(queue, ^{
+                NSString *safeObjectName = [PithosFileUtilities safeSubdirNameForContainerName:node.pithosContainer.name 
+                                                                                    subdirName:@"untitled folder"];
+                ASIPithosObjectRequest *objectRequest = [ASIPithosObjectRequest writeObjectDataRequestWithContainerName:node.pithosContainer.name 
+                                                                                                             objectName:safeObjectName 
+                                                                                                               eTag:nil 
+                                                                                                        contentType:@"application/directory" 
+                                                                                                    contentEncoding:nil 
+                                                                                                 contentDisposition:nil 
+                                                                                                           manifest:nil 
+                                                                                                            sharing:nil 
+                                                                                                           isPublic:ASIPithosObjectRequestPublicIgnore 
+                                                                                                           metadata:nil 
+                                                                                                               data:[NSData data]];
+                objectRequest.delegate = self;
+                objectRequest.didFinishSelector = @selector(newFolderFinished:);
+                objectRequest.didFailSelector = @selector(newFolderFailed:);
+                objectRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+                                          node, @"node", 
+                                          nil];
+                [objectRequest startAsynchronous];
+            });
+        } else if (([node class] == [PithosSubdirNode class]) && 
+                   (node.pithosObject.subdir || 
+                    ![node.pithosObject.name hasSuffix:@"/"])) {
+            dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
+            dispatch_async(queue, ^{
+                NSString *safeObjectName = [PithosFileUtilities safeSubdirNameForContainerName:node.pithosContainer.name 
+                                                                                   subdirName:[node.pithosObject.name stringByAppendingPathComponent:@"untitled folder"]];
+                ASIPithosObjectRequest *objectRequest = [ASIPithosObjectRequest writeObjectDataRequestWithContainerName:node.pithosContainer.name 
+                                                                                                            objectName:safeObjectName 
+                                                                                                                  eTag:nil 
+                                                                                                           contentType:@"application/directory" 
+                                                                                                       contentEncoding:nil 
+                                                                                                    contentDisposition:nil 
+                                                                                                              manifest:nil 
+                                                                                                               sharing:nil 
+                                                                                                              isPublic:ASIPithosObjectRequestPublicIgnore 
+                                                                                                              metadata:nil 
+                                                                                                                  data:[NSData data]];
+                objectRequest.delegate = self;
+                objectRequest.didFinishSelector = @selector(newFolderFinished:);
+                objectRequest.didFailSelector = @selector(newFolderFailed:);
+                objectRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+                                         node, @"node", 
+                                         nil];
+                [objectRequest startAsynchronous];
+            });
+        }
+    }
+}
+
 - (void)getInfo:(NSMenuItem *)sender {
-    for (NSIndexPath *nodeIndexPath in ((NSArray *)[sender representedObject])) {
-        PithosNode *node = [browser itemAtIndexPath:nodeIndexPath];
+    for (PithosNode *node in ((NSArray *)[sender representedObject])) {
         [node showPithosNodeInfo:sender];
     }
 }
 
 - (void)deleteObject:(NSMenuItem *)sender {
-    for (NSIndexPath *nodeIndexPath in ((NSArray *)[sender representedObject])) {
-        PithosNode *node = [browser itemAtIndexPath:nodeIndexPath];
+    for (PithosNode *node in ((NSArray *)[sender representedObject])) {
         if (([node class] == [PithosObjectNode class]) || 
             (([node class] == [PithosSubdirNode class]) && 
              !node.pithosObject.subdir &&
@@ -801,64 +886,71 @@ forDraggedRowsWithIndexes:(NSIndexSet *)rowIndexes inColumn:(NSInteger)column {
             objectRequest.didFailSelector = @selector(deleteObjectFailed:);
             [objectRequest startAsynchronous];
         } else if ([node class] == [PithosSubdirNode class]) {
-            NSArray *objectRequests = [PithosFileUtilities deleteObjectRequestsForSubdirWithContainerName:node.pithosContainer.name 
-                                                                                               objectName:node.pithosObject.name];
-            if (objectRequests) {
-                for (ASIPithosObjectRequest *objectRequest in objectRequests) {
-                    objectRequest.delegate = self;
-                    objectRequest.didFinishSelector = @selector(deleteObjectFinished:);
-                    objectRequest.didFailSelector = @selector(deleteObjectFailed:);
-                    [objectRequest startAsynchronous];
+            dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
+            dispatch_async(queue, ^{
+                NSArray *objectRequests = [PithosFileUtilities deleteObjectRequestsForSubdirWithContainerName:node.pithosContainer.name 
+                                                                                                   objectName:node.pithosObject.name];
+                if (objectRequests) {
+                    for (ASIPithosObjectRequest *objectRequest in objectRequests) {
+                        objectRequest.delegate = self;
+                        objectRequest.didFinishSelector = @selector(deleteObjectFinished:);
+                        objectRequest.didFailSelector = @selector(deleteObjectFailed:);
+                        [objectRequest startAsynchronous];
+                    }
                 }
-            }
-            
+            });
         }
     }
 }
 
 - (void)moveToTrash:(NSMenuItem *)sender {
-    for (NSIndexPath *nodeIndexPath in ((NSArray *)[sender representedObject])) {
-        PithosNode *node = [browser itemAtIndexPath:nodeIndexPath];
+    for (PithosNode *node in ((NSArray *)[sender representedObject])) {
         if (([node class] == [PithosObjectNode class]) || 
             (([node class] == [PithosSubdirNode class]) && 
              !node.pithosObject.subdir &&
              [node.pithosObject.name hasSuffix:@"/"])) {
-            NSString *safeObjectName = [PithosFileUtilities safeObjectNameForContainerName:@"trash" 
-                                                                                objectName:node.pithosObject.name];
-            if (safeObjectName) {
-                ASIPithosObjectRequest *objectRequest = [ASIPithosObjectRequest moveObjectDataRequestWithContainerName:node.pithosContainer.name 
-                                                                                                            objectName:node.pithosObject.name 
-                                                                                                           contentType:nil 
-                                                                                                       contentEncoding:nil 
-                                                                                                    contentDisposition:nil 
-                                                                                                              manifest:nil 
-                                                                                                               sharing:nil 
-                                                                                                              isPublic:ASIPithosObjectRequestPublicIgnore 
-                                                                                                              metadata:nil 
-                                                                                              destinationContainerName:@"trash" 
-                                                                                                 destinationObjectName:safeObjectName];
-                objectRequest.delegate = self;
-                objectRequest.didFinishSelector = @selector(moveToTrashFinished:);
-                objectRequest.didFailSelector = @selector(moveToTrashFailed:);
-                [objectRequest startAsynchronous];
-            }
+            dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
+            dispatch_async(queue, ^{
+                NSString *safeObjectName = [PithosFileUtilities safeObjectNameForContainerName:@"trash" 
+                                                                                    objectName:node.pithosObject.name];
+                if (safeObjectName) {
+                    ASIPithosObjectRequest *objectRequest = [ASIPithosObjectRequest moveObjectDataRequestWithContainerName:node.pithosContainer.name 
+                                                                                                                objectName:node.pithosObject.name 
+                                                                                                               contentType:nil 
+                                                                                                           contentEncoding:nil 
+                                                                                                        contentDisposition:nil 
+                                                                                                                  manifest:nil 
+                                                                                                                   sharing:nil 
+                                                                                                                  isPublic:ASIPithosObjectRequestPublicIgnore 
+                                                                                                                  metadata:nil 
+                                                                                                  destinationContainerName:@"trash" 
+                                                                                                     destinationObjectName:safeObjectName];
+                    objectRequest.delegate = self;
+                    objectRequest.didFinishSelector = @selector(moveToTrashFinished:);
+                    objectRequest.didFailSelector = @selector(moveToTrashFailed:);
+                    [objectRequest startAsynchronous];
+                }
+            });
         } else if ([node class] == [PithosSubdirNode class]) {
-            NSString *safeObjectName = [PithosFileUtilities safeSubdirNameForContainerName:@"trash" 
-                                                                                subdirName:node.pithosObject.name];
-            if (safeObjectName) {
-                NSArray *objectRequests = [PithosFileUtilities moveObjectRequestsForSubdirWithContainerName:node.pithosContainer.name 
-                                                                                                 objectName:node.pithosObject.name 
-                                                                                   destinationContainerName:@"trash" 
-                                                                                      destinationObjectName:safeObjectName];
-                if (objectRequests) {
-                    for (ASIPithosObjectRequest *objectRequest in objectRequests) {
-                        objectRequest.delegate = self;
-                        objectRequest.didFinishSelector = @selector(moveToTrashFinished:);
-                        objectRequest.didFailSelector = @selector(moveToTrashFailed:);
-                        [objectRequest startAsynchronous];
+            dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
+            dispatch_async(queue, ^{
+                NSString *safeObjectName = [PithosFileUtilities safeSubdirNameForContainerName:@"trash" 
+                                                                                    subdirName:node.pithosObject.name];
+                if (safeObjectName) {
+                    NSArray *objectRequests = [PithosFileUtilities moveObjectRequestsForSubdirWithContainerName:node.pithosContainer.name 
+                                                                                                     objectName:node.pithosObject.name 
+                                                                                       destinationContainerName:@"trash" 
+                                                                                          destinationObjectName:safeObjectName];
+                    if (objectRequests) {
+                        for (ASIPithosObjectRequest *objectRequest in objectRequests) {
+                            objectRequest.delegate = self;
+                            objectRequest.didFinishSelector = @selector(moveToTrashFinished:);
+                            objectRequest.didFailSelector = @selector(moveToTrashFailed:);
+                            [objectRequest startAsynchronous];
+                        }
                     }
                 }
-            }        
+            });
         }
     }
 }
@@ -866,6 +958,22 @@ forDraggedRowsWithIndexes:(NSIndexSet *)rowIndexes inColumn:(NSInteger)column {
 #pragma mark -
 #pragma mark Menu Actions ASIHTTPRequestDelegate
 
+- (void)newFolderFinished:(ASIPithosObjectRequest *)objectRequest {
+    if (objectRequest.responseStatusCode == 201) {
+        NSLog(@"New application/directory object created: %@", [objectRequest url]);
+        PithosNode *node = [objectRequest.userInfo objectForKey:@"node"];
+        [node invalidateChildren];
+        node.children;
+    } else {
+        [PithosFileUtilities unexpectedResponseStatusAlertWithRequest:objectRequest];
+    }
+}
+
+- (void)newFolderFailed:(ASIPithosObjectRequest *)objectRequest {
+    NSLog(@"Creation of new application/directory object failed");
+    [PithosFileUtilities httpRequestErrorAlertWithRequest:objectRequest];
+}
+
 - (void)deleteObjectFinished:(ASIPithosObjectRequest *)objectRequest {
     if (objectRequest.responseStatusCode == 204) {
         NSLog(@"Object deleted: %@", [objectRequest url]);
index 75c5879..549a8f2 100644 (file)
     NSFileManager *defaultManager = [NSFileManager defaultManager];
     NSMutableArray *objectRequests = [NSMutableArray arrayWithCapacity:[objects count]];
     NSUInteger subdirPrefixLength = [objectName length];
+
+    NSError *error = nil;
+    [defaultManager createDirectoryAtPath:[directoryPath stringByAppendingPathComponent:subdirName] withIntermediateDirectories:YES attributes:nil error:&error];
+    if (error) {
+        NSLog(@"Cannot create directory at '%@': %@", directoryPath, error);
+        NSAlert *alert = [[[NSAlert alloc] init] autorelease];
+        [alert setMessageText:@"Create Directory Error"];
+        [alert setInformativeText:[NSString stringWithFormat:@"Cannot create directory at '%@': %@", 
+                                   directoryPath, error]];
+        [alert addButtonWithTitle:@"OK"];
+        [alert runModal];
+    }
+    
     for (ASIPithosObject *object in objects) {
         if ([object.contentType isEqualToString:@"application/directory"]) {
             NSString *subdirDirectoryPath = [directoryPath stringByAppendingPathComponent:subdirName];