Statistics
| Branch: | Tag: | Revision:

root / pithos-macos / PithosBrowserController.m @ 46b46b83

History | View | Annotate | Download (155.2 kB)

1 589a14ca Miltiadis Vasilakis
//
2 d8d08dc1 Miltiadis Vasilakis
//  PithosBrowserController.m
3 d8d08dc1 Miltiadis Vasilakis
//  pithos-macos
4 d8d08dc1 Miltiadis Vasilakis
//
5 919cb043 Miltiadis Vasilakis
// Copyright 2011-2012 GRNET S.A. All rights reserved.
6 d8d08dc1 Miltiadis Vasilakis
//
7 e5fdf4d9 Miltiadis Vasilakis
// Redistribution and use in source and binary forms, with or
8 e5fdf4d9 Miltiadis Vasilakis
// without modification, are permitted provided that the following
9 e5fdf4d9 Miltiadis Vasilakis
// conditions are met:
10 e5fdf4d9 Miltiadis Vasilakis
// 
11 e5fdf4d9 Miltiadis Vasilakis
//   1. Redistributions of source code must retain the above
12 e5fdf4d9 Miltiadis Vasilakis
//      copyright notice, this list of conditions and the following
13 e5fdf4d9 Miltiadis Vasilakis
//      disclaimer.
14 e5fdf4d9 Miltiadis Vasilakis
// 
15 e5fdf4d9 Miltiadis Vasilakis
//   2. Redistributions in binary form must reproduce the above
16 e5fdf4d9 Miltiadis Vasilakis
//      copyright notice, this list of conditions and the following
17 e5fdf4d9 Miltiadis Vasilakis
//      disclaimer in the documentation and/or other materials
18 e5fdf4d9 Miltiadis Vasilakis
//      provided with the distribution.
19 e5fdf4d9 Miltiadis Vasilakis
// 
20 e5fdf4d9 Miltiadis Vasilakis
// THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
21 e5fdf4d9 Miltiadis Vasilakis
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 e5fdf4d9 Miltiadis Vasilakis
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 e5fdf4d9 Miltiadis Vasilakis
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
24 e5fdf4d9 Miltiadis Vasilakis
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 e5fdf4d9 Miltiadis Vasilakis
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 e5fdf4d9 Miltiadis Vasilakis
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
27 e5fdf4d9 Miltiadis Vasilakis
// USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 e5fdf4d9 Miltiadis Vasilakis
// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 e5fdf4d9 Miltiadis Vasilakis
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 e5fdf4d9 Miltiadis Vasilakis
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 e5fdf4d9 Miltiadis Vasilakis
// POSSIBILITY OF SUCH DAMAGE.
32 e5fdf4d9 Miltiadis Vasilakis
// 
33 e5fdf4d9 Miltiadis Vasilakis
// The views and conclusions contained in the software and
34 e5fdf4d9 Miltiadis Vasilakis
// documentation are those of the authors and should not be
35 e5fdf4d9 Miltiadis Vasilakis
// interpreted as representing official policies, either expressed
36 e5fdf4d9 Miltiadis Vasilakis
// or implied, of GRNET S.A.
37 d8d08dc1 Miltiadis Vasilakis
38 d8d08dc1 Miltiadis Vasilakis
#import "PithosBrowserController.h"
39 4bf68b77 Miltiadis Vasilakis
#import "PithosNode.h"
40 9f3a92de Miltiadis Vasilakis
#import "PithosAccountNode.h"
41 9f3a92de Miltiadis Vasilakis
#import "PithosContainerNode.h"
42 6dc7e931 Miltiadis Vasilakis
#import "PithosSubdirNode.h"
43 6dc7e931 Miltiadis Vasilakis
#import "PithosObjectNode.h"
44 af3b9f06 Miltiadis Vasilakis
#import "PithosSharingAccountsNode.h"
45 9f3a92de Miltiadis Vasilakis
#import "PithosEmptyNode.h"
46 e5fdf4d9 Miltiadis Vasilakis
#import "ImageAndTextCell.h"
47 9f3a92de Miltiadis Vasilakis
#import "FileSystemBrowserCell.h"
48 4c1c46fd Miltiadis Vasilakis
#import "ASINetworkQueue.h"
49 4bf68b77 Miltiadis Vasilakis
#import "ASIPithosRequest.h"
50 919cb043 Miltiadis Vasilakis
#import "ASIPithos.h"
51 4bf68b77 Miltiadis Vasilakis
#import "ASIPithosContainerRequest.h"
52 6dc7e931 Miltiadis Vasilakis
#import "ASIPithosObjectRequest.h"
53 470e6f81 Miltiadis Vasilakis
#import "ASIPithosAccount.h"
54 4bf68b77 Miltiadis Vasilakis
#import "ASIPithosContainer.h"
55 6dc7e931 Miltiadis Vasilakis
#import "ASIPithosObject.h"
56 1b1e6fa1 Miltiadis Vasilakis
#import "PithosUtilities.h"
57 2943d6d4 Miltiadis Vasilakis
#import "UsingSizeTransformer.h"
58 d8d08dc1 Miltiadis Vasilakis
59 9f3a92de Miltiadis Vasilakis
@interface PithosBrowserCell : FileSystemBrowserCell {}
60 e5fdf4d9 Miltiadis Vasilakis
@end
61 d8d08dc1 Miltiadis Vasilakis
62 e5fdf4d9 Miltiadis Vasilakis
@implementation PithosBrowserCell
63 d8d08dc1 Miltiadis Vasilakis
64 9f3a92de Miltiadis Vasilakis
- (id)init {
65 9f3a92de Miltiadis Vasilakis
    if ((self = [super init])) {
66 9f3a92de Miltiadis Vasilakis
        [self setLineBreakMode:NSLineBreakByTruncatingMiddle];
67 19c353fe Miltiadis Vasilakis
        [self setEditable:YES];
68 9f3a92de Miltiadis Vasilakis
    }
69 9f3a92de Miltiadis Vasilakis
    return self;
70 9f3a92de Miltiadis Vasilakis
}
71 9f3a92de Miltiadis Vasilakis
72 e5fdf4d9 Miltiadis Vasilakis
- (void)setObjectValue:(id)object {
73 e5fdf4d9 Miltiadis Vasilakis
    if ([object isKindOfClass:[PithosNode class]]) {
74 e5fdf4d9 Miltiadis Vasilakis
        PithosNode *node = (PithosNode *)object;
75 e5fdf4d9 Miltiadis Vasilakis
        [self setStringValue:node.displayName];
76 e5fdf4d9 Miltiadis Vasilakis
        [self setImage:node.icon];
77 e5fdf4d9 Miltiadis Vasilakis
    } else {
78 e5fdf4d9 Miltiadis Vasilakis
        [super setObjectValue:object];
79 d8d08dc1 Miltiadis Vasilakis
    }
80 d8d08dc1 Miltiadis Vasilakis
}
81 d8d08dc1 Miltiadis Vasilakis
82 e5fdf4d9 Miltiadis Vasilakis
@end
83 e5fdf4d9 Miltiadis Vasilakis
84 e5fdf4d9 Miltiadis Vasilakis
@interface PithosOutlineViewCell : ImageAndTextCell {}
85 e5fdf4d9 Miltiadis Vasilakis
@end
86 e5fdf4d9 Miltiadis Vasilakis
87 e5fdf4d9 Miltiadis Vasilakis
@implementation PithosOutlineViewCell
88 e5fdf4d9 Miltiadis Vasilakis
89 e5fdf4d9 Miltiadis Vasilakis
- (void)setObjectValue:(id)object {
90 e5fdf4d9 Miltiadis Vasilakis
    if ([object isKindOfClass:[PithosNode class]]) {
91 e5fdf4d9 Miltiadis Vasilakis
        PithosNode *node = (PithosNode *)object;
92 e5fdf4d9 Miltiadis Vasilakis
        [self setStringValue:node.displayName];
93 e5fdf4d9 Miltiadis Vasilakis
        [self setImage:node.icon];
94 e5fdf4d9 Miltiadis Vasilakis
        [self setEditable:NO];
95 e5fdf4d9 Miltiadis Vasilakis
    } else {
96 e5fdf4d9 Miltiadis Vasilakis
        [super setObjectValue:object];
97 e5fdf4d9 Miltiadis Vasilakis
    }
98 e5fdf4d9 Miltiadis Vasilakis
}
99 e5fdf4d9 Miltiadis Vasilakis
100 e5fdf4d9 Miltiadis Vasilakis
@end
101 e5fdf4d9 Miltiadis Vasilakis
102 0224a49f Miltiadis Vasilakis
@interface PithosBrowserController (Private)
103 67e3336f Miltiadis Vasilakis
- (BOOL)uploadFiles:(NSArray *)filenames toNode:(PithosNode *)destinationNode;
104 67e3336f Miltiadis Vasilakis
- (BOOL)moveNodes:(NSArray *)nodes toNode:(PithosNode *)destinationNode;
105 67e3336f Miltiadis Vasilakis
- (BOOL)copyNodes:(NSArray *)nodes toNode:(PithosNode *)destinationNode;
106 e5fdf4d9 Miltiadis Vasilakis
@end
107 e5fdf4d9 Miltiadis Vasilakis
108 e5fdf4d9 Miltiadis Vasilakis
@implementation PithosBrowserController
109 919cb043 Miltiadis Vasilakis
@synthesize pithos;
110 470e6f81 Miltiadis Vasilakis
@synthesize accountNode;
111 212a7d57 Miltiadis Vasilakis
@synthesize verticalSplitView, horizontalSplitView, leftTopView, leftBottomView, outlineView, browser, outlineViewMenu, browserMenu;
112 c950a94d Miltiadis Vasilakis
@synthesize draggedNodes, draggedParentNode;
113 c950a94d Miltiadis Vasilakis
@synthesize clipboardNodes, clipboardParentNode, clipboardCopy;
114 470e6f81 Miltiadis Vasilakis
@synthesize activityTextField, activityProgressIndicator;
115 e5fdf4d9 Miltiadis Vasilakis
116 e5fdf4d9 Miltiadis Vasilakis
#pragma mark -
117 e5fdf4d9 Miltiadis Vasilakis
#pragma Object Lifecycle
118 e5fdf4d9 Miltiadis Vasilakis
119 e5fdf4d9 Miltiadis Vasilakis
- (id)init {
120 e5fdf4d9 Miltiadis Vasilakis
    return [super initWithWindowNibName:@"PithosBrowserController"];
121 e5fdf4d9 Miltiadis Vasilakis
}
122 e5fdf4d9 Miltiadis Vasilakis
123 d8426ffb Miltiadis Vasilakis
- (void)windowDidLoad {
124 d8426ffb Miltiadis Vasilakis
    [super windowDidLoad];
125 d8426ffb Miltiadis Vasilakis
    if (browser && !browserInitialized) {
126 d8426ffb Miltiadis Vasilakis
        browserInitialized = YES;
127 d8426ffb Miltiadis Vasilakis
        [self initBrowser];
128 d8426ffb Miltiadis Vasilakis
    }
129 d8d08dc1 Miltiadis Vasilakis
}
130 d8d08dc1 Miltiadis Vasilakis
131 919cb043 Miltiadis Vasilakis
- (void)initBrowser {
132 d41b3577 Miltiadis Vasilakis
    [browser registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, NSFilesPromisePboardType, nil]];
133 d41b3577 Miltiadis Vasilakis
    [browser setDraggingSourceOperationMask:(NSDragOperationCopy|NSDragOperationMove) forLocal:YES];
134 6dc7e931 Miltiadis Vasilakis
    [browser setDraggingSourceOperationMask:NSDragOperationCopy forLocal:NO];
135 6dc7e931 Miltiadis Vasilakis
    
136 67e3336f Miltiadis Vasilakis
    [outlineView registerForDraggedTypes:[NSArray arrayWithObjects:NSFilenamesPboardType, NSFilesPromisePboardType, nil]];
137 67e3336f Miltiadis Vasilakis
    [outlineView setDraggingSourceOperationMask:(NSDragOperationCopy|NSDragOperationMove) forLocal:YES];
138 67e3336f Miltiadis Vasilakis
    [outlineView setDraggingSourceOperationMask:NSDragOperationCopy forLocal:NO];
139 67e3336f Miltiadis Vasilakis
    
140 e5fdf4d9 Miltiadis Vasilakis
    [browser setCellClass:[PithosBrowserCell class]];
141 919cb043 Miltiadis Vasilakis
    [browser setAllowsBranchSelection:YES];
142 919cb043 Miltiadis Vasilakis
    [browser setAllowsMultipleSelection:YES];
143 919cb043 Miltiadis Vasilakis
    [browser setAllowsEmptySelection:YES];
144 919cb043 Miltiadis Vasilakis
    [browser setAllowsTypeSelect:YES];
145 4c1c46fd Miltiadis Vasilakis
    
146 4c1c46fd Miltiadis Vasilakis
    moveNetworkQueue = [[ASINetworkQueue alloc] init];
147 4c1c46fd Miltiadis Vasilakis
    moveNetworkQueue.shouldCancelAllRequestsOnFailure = NO;
148 d8426ffb Miltiadis Vasilakis
//    moveNetworkQueue.maxConcurrentOperationCount = 1;
149 4c1c46fd Miltiadis Vasilakis
    copyNetworkQueue = [[ASINetworkQueue alloc] init];
150 4c1c46fd Miltiadis Vasilakis
    copyNetworkQueue.shouldCancelAllRequestsOnFailure = NO;
151 d8426ffb Miltiadis Vasilakis
//    copyNetworkQueue.maxConcurrentOperationCount = 1;
152 4c1c46fd Miltiadis Vasilakis
    deleteNetworkQueue = [[ASINetworkQueue alloc] init];
153 4c1c46fd Miltiadis Vasilakis
    deleteNetworkQueue.shouldCancelAllRequestsOnFailure = NO;
154 d8426ffb Miltiadis Vasilakis
//    deleteNetworkQueue.maxConcurrentOperationCount = 1;
155 4c1c46fd Miltiadis Vasilakis
    uploadNetworkQueue = [[ASINetworkQueue alloc] init];
156 4c1c46fd Miltiadis Vasilakis
    uploadNetworkQueue.showAccurateProgress = YES;
157 4c1c46fd Miltiadis Vasilakis
    uploadNetworkQueue.shouldCancelAllRequestsOnFailure = NO;
158 d8426ffb Miltiadis Vasilakis
//    uploadNetworkQueue.maxConcurrentOperationCount = 1;
159 4c1c46fd Miltiadis Vasilakis
    downloadNetworkQueue = [[ASINetworkQueue alloc] init];
160 4c1c46fd Miltiadis Vasilakis
    downloadNetworkQueue.showAccurateProgress = YES;
161 4c1c46fd Miltiadis Vasilakis
    downloadNetworkQueue.shouldCancelAllRequestsOnFailure = NO;
162 d8426ffb Miltiadis Vasilakis
//    downloadNetworkQueue.maxConcurrentOperationCount = 1;
163 d8426ffb Miltiadis Vasilakis
    
164 d8426ffb Miltiadis Vasilakis
    moveQueue = [[NSOperationQueue alloc] init];
165 d8426ffb Miltiadis Vasilakis
    [moveQueue setSuspended:YES];
166 d8426ffb Miltiadis Vasilakis
    moveQueue.name = @"gr.grnet.pithos.MoveQueue";
167 d8426ffb Miltiadis Vasilakis
//    moveQueue.maxConcurrentOperationCount = 1;
168 d8426ffb Miltiadis Vasilakis
    copyQueue = [[NSOperationQueue alloc] init];
169 d8426ffb Miltiadis Vasilakis
    [copyQueue setSuspended:YES];
170 d8426ffb Miltiadis Vasilakis
    copyQueue.name = @"gr.grnet.pithos.CopyQueue";
171 d8426ffb Miltiadis Vasilakis
//    copyQueue.maxConcurrentOperationCount = 1;
172 d8426ffb Miltiadis Vasilakis
    deleteQueue = [[NSOperationQueue alloc] init];
173 d8426ffb Miltiadis Vasilakis
    [deleteQueue setSuspended:YES];
174 d8426ffb Miltiadis Vasilakis
    deleteQueue.name = @"gr.grnet.pithos.DeleteQueue";
175 d8426ffb Miltiadis Vasilakis
//    deleteQueue.maxConcurrentOperationCount = 1;
176 d8426ffb Miltiadis Vasilakis
    uploadQueue = [[NSOperationQueue alloc] init];
177 d8426ffb Miltiadis Vasilakis
    [uploadQueue setSuspended:YES];
178 d8426ffb Miltiadis Vasilakis
    uploadQueue.name = @"gr.grnet.pithos.UploadQueue";
179 d8426ffb Miltiadis Vasilakis
//    uploadQueue.maxConcurrentOperationCount = 1;
180 d8426ffb Miltiadis Vasilakis
    downloadQueue = [[NSOperationQueue alloc] init];
181 d8426ffb Miltiadis Vasilakis
    [downloadQueue setSuspended:YES];
182 d8426ffb Miltiadis Vasilakis
    downloadQueue.name = @"gr.grnet.pithos.DownloadQueue";
183 d8426ffb Miltiadis Vasilakis
//    downloadQueue.maxConcurrentOperationCount = 1;
184 4c1c46fd Miltiadis Vasilakis
    
185 d8426ffb Miltiadis Vasilakis
    moveCallbackQueue = [[NSOperationQueue alloc] init];
186 d8426ffb Miltiadis Vasilakis
    [moveCallbackQueue setSuspended:YES];
187 d8426ffb Miltiadis Vasilakis
    moveCallbackQueue.name = @"gr.grnet.pithos.MoveCallbackQueue";
188 d8426ffb Miltiadis Vasilakis
//    moveCallbackQueue.maxConcurrentOperationCount = 1;
189 d8426ffb Miltiadis Vasilakis
    copyCallbackQueue = [[NSOperationQueue alloc] init];
190 d8426ffb Miltiadis Vasilakis
    [copyCallbackQueue setSuspended:YES];
191 d8426ffb Miltiadis Vasilakis
    copyCallbackQueue.name = @"gr.grnet.pithos.CopyCallbackQueue";
192 d8426ffb Miltiadis Vasilakis
//    copyCallbackQueue.maxConcurrentOperationCount = 1;
193 d8426ffb Miltiadis Vasilakis
    deleteCallbackQueue = [[NSOperationQueue alloc] init];
194 d8426ffb Miltiadis Vasilakis
    [deleteCallbackQueue setSuspended:YES];
195 d8426ffb Miltiadis Vasilakis
    deleteCallbackQueue.name = @"gr.grnet.pithos.DeleteCallbackQueue";
196 d8426ffb Miltiadis Vasilakis
//    deleteCallbackQueue.maxConcurrentOperationCount = 1;
197 d8426ffb Miltiadis Vasilakis
    uploadCallbackQueue = [[NSOperationQueue alloc] init];
198 d8426ffb Miltiadis Vasilakis
    [uploadCallbackQueue setSuspended:YES];
199 d8426ffb Miltiadis Vasilakis
    uploadCallbackQueue.name = @"gr.grnet.pithos.UploadCallbackQueue";
200 d8426ffb Miltiadis Vasilakis
//    uploadCallbackQueue.maxConcurrentOperationCount = 1;
201 d8426ffb Miltiadis Vasilakis
    downloadCallbackQueue = [[NSOperationQueue alloc] init];
202 d8426ffb Miltiadis Vasilakis
    [downloadCallbackQueue setSuspended:YES];
203 d8426ffb Miltiadis Vasilakis
    downloadCallbackQueue.name = @"gr.grnet.pithos.DownloadCallbackQueue";
204 d8426ffb Miltiadis Vasilakis
//    downloadCallbackQueue.maxConcurrentOperationCount = 1;
205 2d9996a2 Miltiadis Vasilakis
    
206 470e6f81 Miltiadis Vasilakis
    [activityProgressIndicator setUsesThreadedAnimation:YES];
207 470e6f81 Miltiadis Vasilakis
    [activityProgressIndicator setMinValue:0.0];
208 470e6f81 Miltiadis Vasilakis
    [activityProgressIndicator setMaxValue:1.0];
209 470e6f81 Miltiadis Vasilakis
    activityFacility = [PithosActivityFacility defaultPithosActivityFacility];
210 470e6f81 Miltiadis Vasilakis
    
211 919cb043 Miltiadis Vasilakis
    self.accountNode = [[[PithosAccountNode alloc] initWithPithos:pithos] autorelease];
212 20f54e18 Miltiadis Vasilakis
    containersNode = [[PithosEmptyNode alloc] initWithDisplayName:@"CONTAINERS" icon:nil];
213 20f54e18 Miltiadis Vasilakis
    containersNodeChildren = [[NSMutableArray alloc] init];
214 20f54e18 Miltiadis Vasilakis
    sharedNode = [[PithosEmptyNode alloc] initWithDisplayName:@"SHARED" icon:nil];
215 919cb043 Miltiadis Vasilakis
    mySharedNode = [[PithosAccountNode alloc] initWithPithos:pithos];
216 20f54e18 Miltiadis Vasilakis
    mySharedNode.displayName = @"my shared";
217 20f54e18 Miltiadis Vasilakis
    mySharedNode.shared = YES;
218 20f54e18 Miltiadis Vasilakis
    mySharedNode.icon = [[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kUserIcon)];
219 919cb043 Miltiadis Vasilakis
    othersSharedNode = [[PithosSharingAccountsNode alloc] initWithPithos:pithos];
220 af3b9f06 Miltiadis Vasilakis
    othersSharedNode.displayName = @"others shared";
221 af3b9f06 Miltiadis Vasilakis
    othersSharedNode.icon = [[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kGroupIcon)];
222 4ae10a2b Miltiadis Vasilakis
    
223 e5fdf4d9 Miltiadis Vasilakis
    [[[outlineView tableColumns] objectAtIndex:0] setDataCell:[[[PithosOutlineViewCell alloc] init] autorelease]];
224 e5fdf4d9 Miltiadis Vasilakis
    
225 e5fdf4d9 Miltiadis Vasilakis
    // Register for updates
226 af3b9f06 Miltiadis Vasilakis
    // PithosContainerNode updates browser nodes
227 e5fdf4d9 Miltiadis Vasilakis
    [[NSNotificationCenter defaultCenter] addObserver:self 
228 e5fdf4d9 Miltiadis Vasilakis
                                             selector:@selector(pithosNodeChildrenUpdated:) 
229 63db4b97 Miltiadis Vasilakis
                                                 name:@"PithosContainerNodeChildrenUpdated" 
230 e5fdf4d9 Miltiadis Vasilakis
                                               object:nil];
231 af3b9f06 Miltiadis Vasilakis
    // PithosSubdirNode updates browser nodes
232 63db4b97 Miltiadis Vasilakis
    [[NSNotificationCenter defaultCenter] addObserver:self 
233 63db4b97 Miltiadis Vasilakis
                                             selector:@selector(pithosNodeChildrenUpdated:) 
234 63db4b97 Miltiadis Vasilakis
                                                 name:@"PithosSubdirNodeChildrenUpdated" 
235 63db4b97 Miltiadis Vasilakis
                                               object:nil];
236 af3b9f06 Miltiadis Vasilakis
    // PithosAccountNode accountNode updates outlineView container nodes 
237 589a14ca Miltiadis Vasilakis
    [[NSNotificationCenter defaultCenter] addObserver:self 
238 4bf68b77 Miltiadis Vasilakis
                                             selector:@selector(pithosAccountNodeChildrenUpdated:) 
239 4bf68b77 Miltiadis Vasilakis
                                                 name:@"PithosAccountNodeChildrenUpdated" 
240 4ae10a2b Miltiadis Vasilakis
                                               object:accountNode];
241 af3b9f06 Miltiadis Vasilakis
    // PithosAccountNode other than accountNode updates nodes 
242 4ae10a2b Miltiadis Vasilakis
    [[NSNotificationCenter defaultCenter] addObserver:self 
243 4ae10a2b Miltiadis Vasilakis
                                             selector:@selector(pithosNodeChildrenUpdated:) 
244 4ae10a2b Miltiadis Vasilakis
                                                 name:@"PithosAccountNodeChildrenUpdated" 
245 af3b9f06 Miltiadis Vasilakis
                                               object:nil];
246 af3b9f06 Miltiadis Vasilakis
    // PithosSharingAccountsNode othersSharedNode updates browser nodes 
247 af3b9f06 Miltiadis Vasilakis
    [[NSNotificationCenter defaultCenter] addObserver:self 
248 af3b9f06 Miltiadis Vasilakis
                                             selector:@selector(pithosNodeChildrenUpdated:) 
249 af3b9f06 Miltiadis Vasilakis
                                                 name:@"PithosSharingAccountsNodeChildrenUpdated" 
250 af3b9f06 Miltiadis Vasilakis
                                               object:othersSharedNode];
251 af3b9f06 Miltiadis Vasilakis
    // Request for browser refresh 
252 20f54e18 Miltiadis Vasilakis
    [[NSNotificationCenter defaultCenter] addObserver:self 
253 20f54e18 Miltiadis Vasilakis
                                             selector:@selector(pithosBrowserRefreshNeeded:) 
254 20f54e18 Miltiadis Vasilakis
                                                 name:@"PithosBrowserRefreshNeeeded" 
255 919cb043 Miltiadis Vasilakis
                                               object:nil];
256 919cb043 Miltiadis Vasilakis
}
257 919cb043 Miltiadis Vasilakis
258 919cb043 Miltiadis Vasilakis
- (void)resetBrowser {
259 d8426ffb Miltiadis Vasilakis
    @synchronized(self) {
260 d8426ffb Miltiadis Vasilakis
        if (!browserActive)
261 d8426ffb Miltiadis Vasilakis
            return;
262 d8426ffb Miltiadis Vasilakis
    }
263 d8426ffb Miltiadis Vasilakis
264 919cb043 Miltiadis Vasilakis
    [refreshTimer invalidate];
265 919cb043 Miltiadis Vasilakis
    [refreshTimer release];
266 919cb043 Miltiadis Vasilakis
    
267 d8426ffb Miltiadis Vasilakis
    [moveNetworkQueue reset];
268 d8426ffb Miltiadis Vasilakis
    [copyNetworkQueue reset];
269 d8426ffb Miltiadis Vasilakis
    [deleteNetworkQueue reset];
270 d8426ffb Miltiadis Vasilakis
    [uploadNetworkQueue reset];
271 d8426ffb Miltiadis Vasilakis
    [downloadNetworkQueue reset];
272 919cb043 Miltiadis Vasilakis
    
273 d8426ffb Miltiadis Vasilakis
    [moveQueue cancelAllOperations];
274 d8426ffb Miltiadis Vasilakis
    [moveQueue setSuspended:YES];
275 d8426ffb Miltiadis Vasilakis
    [copyQueue cancelAllOperations];
276 d8426ffb Miltiadis Vasilakis
    [copyQueue setSuspended:YES];
277 d8426ffb Miltiadis Vasilakis
    [deleteQueue cancelAllOperations];
278 d8426ffb Miltiadis Vasilakis
    [deleteQueue setSuspended:YES];
279 d8426ffb Miltiadis Vasilakis
    [uploadQueue cancelAllOperations];
280 d8426ffb Miltiadis Vasilakis
    [uploadQueue setSuspended:YES];
281 d8426ffb Miltiadis Vasilakis
    [downloadQueue cancelAllOperations];
282 d8426ffb Miltiadis Vasilakis
    [downloadQueue setSuspended:YES];
283 d8426ffb Miltiadis Vasilakis
284 d8426ffb Miltiadis Vasilakis
    [moveCallbackQueue cancelAllOperations];
285 d8426ffb Miltiadis Vasilakis
    [moveCallbackQueue setSuspended:YES];
286 d8426ffb Miltiadis Vasilakis
    [copyCallbackQueue cancelAllOperations];
287 d8426ffb Miltiadis Vasilakis
    [copyCallbackQueue setSuspended:YES];
288 d8426ffb Miltiadis Vasilakis
    [deleteCallbackQueue cancelAllOperations];
289 d8426ffb Miltiadis Vasilakis
    [deleteCallbackQueue setSuspended:YES];
290 d8426ffb Miltiadis Vasilakis
    [uploadCallbackQueue cancelAllOperations];
291 d8426ffb Miltiadis Vasilakis
    [uploadCallbackQueue setSuspended:YES];
292 d8426ffb Miltiadis Vasilakis
    [downloadCallbackQueue cancelAllOperations];
293 d8426ffb Miltiadis Vasilakis
    [downloadCallbackQueue setSuspended:YES];
294 d8426ffb Miltiadis Vasilakis
295 919cb043 Miltiadis Vasilakis
    rootNode = nil;
296 919cb043 Miltiadis Vasilakis
    [browser loadColumnZero];
297 919cb043 Miltiadis Vasilakis
    [containersNodeChildren removeAllObjects];
298 919cb043 Miltiadis Vasilakis
    [outlineView reloadData];
299 d8426ffb Miltiadis Vasilakis
    // Expand the folder outline view
300 919cb043 Miltiadis Vasilakis
    [outlineView expandItem:nil expandChildren:YES];
301 d8426ffb Miltiadis Vasilakis
    [outlineView selectRowIndexes:[NSIndexSet indexSetWithIndex:1] byExtendingSelection:NO];
302 919cb043 Miltiadis Vasilakis
    
303 919cb043 Miltiadis Vasilakis
    activityFacility.delegate = nil;
304 919cb043 Miltiadis Vasilakis
    [activityProgressIndicator setDoubleValue:1.0];
305 919cb043 Miltiadis Vasilakis
    [activityProgressIndicator stopAnimation:self];
306 d8426ffb Miltiadis Vasilakis
    
307 d8426ffb Miltiadis Vasilakis
    @synchronized(self) {
308 d8426ffb Miltiadis Vasilakis
        browserActive = NO;
309 d8426ffb Miltiadis Vasilakis
    }
310 919cb043 Miltiadis Vasilakis
}
311 919cb043 Miltiadis Vasilakis
312 919cb043 Miltiadis Vasilakis
- (void)startBrowser {
313 d8426ffb Miltiadis Vasilakis
    @synchronized(self) {
314 d8426ffb Miltiadis Vasilakis
        if (browserActive)
315 d8426ffb Miltiadis Vasilakis
            return;
316 d8426ffb Miltiadis Vasilakis
    }
317 d8426ffb Miltiadis Vasilakis
    
318 d8426ffb Miltiadis Vasilakis
    // In the improbable case of leftover operations
319 d8426ffb Miltiadis Vasilakis
    [moveNetworkQueue reset];
320 d8426ffb Miltiadis Vasilakis
    [copyNetworkQueue reset];
321 d8426ffb Miltiadis Vasilakis
    [deleteNetworkQueue reset];
322 d8426ffb Miltiadis Vasilakis
    [uploadNetworkQueue reset];
323 d8426ffb Miltiadis Vasilakis
    [downloadNetworkQueue reset];
324 d8426ffb Miltiadis Vasilakis
    [moveQueue cancelAllOperations];
325 d8426ffb Miltiadis Vasilakis
    [copyQueue cancelAllOperations];
326 d8426ffb Miltiadis Vasilakis
    [deleteQueue cancelAllOperations];
327 d8426ffb Miltiadis Vasilakis
    [uploadQueue cancelAllOperations];
328 d8426ffb Miltiadis Vasilakis
    [downloadQueue cancelAllOperations];
329 d8426ffb Miltiadis Vasilakis
    [moveCallbackQueue cancelAllOperations];
330 d8426ffb Miltiadis Vasilakis
    [copyCallbackQueue cancelAllOperations];
331 d8426ffb Miltiadis Vasilakis
    [deleteCallbackQueue cancelAllOperations];
332 d8426ffb Miltiadis Vasilakis
    [uploadCallbackQueue cancelAllOperations];
333 d8426ffb Miltiadis Vasilakis
    [downloadCallbackQueue cancelAllOperations];
334 d8426ffb Miltiadis Vasilakis
335 d8426ffb Miltiadis Vasilakis
    [moveNetworkQueue go];
336 d8426ffb Miltiadis Vasilakis
    [copyNetworkQueue go];
337 d8426ffb Miltiadis Vasilakis
    [deleteNetworkQueue go];
338 d8426ffb Miltiadis Vasilakis
    [uploadNetworkQueue go];
339 d8426ffb Miltiadis Vasilakis
    [downloadNetworkQueue go];
340 d8426ffb Miltiadis Vasilakis
    [moveQueue setSuspended:NO];
341 d8426ffb Miltiadis Vasilakis
    [copyQueue setSuspended:NO];
342 d8426ffb Miltiadis Vasilakis
    [deleteQueue setSuspended:NO];
343 d8426ffb Miltiadis Vasilakis
    [uploadQueue setSuspended:NO];
344 d8426ffb Miltiadis Vasilakis
    [downloadQueue setSuspended:NO];
345 d8426ffb Miltiadis Vasilakis
    [moveCallbackQueue setSuspended:NO];
346 d8426ffb Miltiadis Vasilakis
    [copyCallbackQueue setSuspended:NO];
347 d8426ffb Miltiadis Vasilakis
    [deleteCallbackQueue setSuspended:NO];
348 d8426ffb Miltiadis Vasilakis
    [uploadCallbackQueue setSuspended:NO];
349 d8426ffb Miltiadis Vasilakis
    [downloadCallbackQueue setSuspended:NO];
350 d8426ffb Miltiadis Vasilakis
351 919cb043 Miltiadis Vasilakis
    accountNode.pithos = pithos;
352 d8426ffb Miltiadis Vasilakis
    [accountNode forceRefresh];
353 919cb043 Miltiadis Vasilakis
    mySharedNode.pithos = pithos;
354 d8426ffb Miltiadis Vasilakis
    [mySharedNode forceRefresh];
355 919cb043 Miltiadis Vasilakis
    othersSharedNode.pithos = pithos;
356 d8426ffb Miltiadis Vasilakis
    [othersSharedNode forceRefresh];
357 d8426ffb Miltiadis Vasilakis
            
358 d8426ffb Miltiadis Vasilakis
//    [activityFacility reset];
359 919cb043 Miltiadis Vasilakis
    activityFacility.delegate = self;
360 d8426ffb Miltiadis Vasilakis
            
361 d8426ffb Miltiadis Vasilakis
    refreshTimer = [[NSTimer scheduledTimerWithTimeInterval:30 
362 d8426ffb Miltiadis Vasilakis
                                                     target:self 
363 d8426ffb Miltiadis Vasilakis
                                                   selector:@selector(forceRefresh:) 
364 d8426ffb Miltiadis Vasilakis
                                                   userInfo:self 
365 d8426ffb Miltiadis Vasilakis
                                                    repeats:YES] retain];
366 d8426ffb Miltiadis Vasilakis
    @synchronized(self) {
367 d8426ffb Miltiadis Vasilakis
        browserActive = YES;
368 d8426ffb Miltiadis Vasilakis
    }
369 919cb043 Miltiadis Vasilakis
}
370 919cb043 Miltiadis Vasilakis
371 d8426ffb Miltiadis Vasilakis
- (BOOL)operationsPending {
372 d8426ffb Miltiadis Vasilakis
    return ([moveNetworkQueue operationCount] || 
373 d8426ffb Miltiadis Vasilakis
            [copyNetworkQueue operationCount] || 
374 d8426ffb Miltiadis Vasilakis
            [deleteNetworkQueue operationCount] || 
375 d8426ffb Miltiadis Vasilakis
            [uploadNetworkQueue operationCount] || 
376 d8426ffb Miltiadis Vasilakis
            [downloadNetworkQueue operationCount] || 
377 d8426ffb Miltiadis Vasilakis
            [moveQueue operationCount] || 
378 d8426ffb Miltiadis Vasilakis
            [copyQueue operationCount] || 
379 d8426ffb Miltiadis Vasilakis
            [deleteQueue operationCount] || 
380 d8426ffb Miltiadis Vasilakis
            [uploadQueue operationCount] || 
381 d8426ffb Miltiadis Vasilakis
            [downloadQueue operationCount] || 
382 d8426ffb Miltiadis Vasilakis
            [moveCallbackQueue operationCount] || 
383 d8426ffb Miltiadis Vasilakis
            [copyCallbackQueue operationCount] || 
384 d8426ffb Miltiadis Vasilakis
            [deleteCallbackQueue operationCount] || 
385 d8426ffb Miltiadis Vasilakis
            [uploadCallbackQueue operationCount] || 
386 d8426ffb Miltiadis Vasilakis
            [downloadCallbackQueue operationCount]);
387 919cb043 Miltiadis Vasilakis
}
388 919cb043 Miltiadis Vasilakis
389 d8426ffb Miltiadis Vasilakis
- (void)dealloc {
390 d8426ffb Miltiadis Vasilakis
    [[NSNotificationCenter defaultCenter] removeObserver:self];
391 d8426ffb Miltiadis Vasilakis
    [self resetBrowser];
392 d8426ffb Miltiadis Vasilakis
    [moveQueue release];
393 d8426ffb Miltiadis Vasilakis
    [copyQueue release];
394 d8426ffb Miltiadis Vasilakis
    [deleteQueue release];
395 d8426ffb Miltiadis Vasilakis
    [uploadQueue release];
396 d8426ffb Miltiadis Vasilakis
    [downloadQueue release];
397 d8426ffb Miltiadis Vasilakis
    [moveNetworkQueue release];
398 d8426ffb Miltiadis Vasilakis
    [copyNetworkQueue release];
399 d8426ffb Miltiadis Vasilakis
    [deleteNetworkQueue release];
400 d8426ffb Miltiadis Vasilakis
    [uploadNetworkQueue release];
401 d8426ffb Miltiadis Vasilakis
    [downloadNetworkQueue release];
402 d8426ffb Miltiadis Vasilakis
    [clipboardParentNode release];
403 d8426ffb Miltiadis Vasilakis
    [clipboardNodes release];
404 d8426ffb Miltiadis Vasilakis
    [draggedParentNode release];
405 d8426ffb Miltiadis Vasilakis
    [draggedNodes release];
406 d8426ffb Miltiadis Vasilakis
    [sharedPreviewController release];
407 d8426ffb Miltiadis Vasilakis
    [othersSharedNode release];
408 d8426ffb Miltiadis Vasilakis
    [mySharedNode release];
409 d8426ffb Miltiadis Vasilakis
    [sharedNode release];
410 d8426ffb Miltiadis Vasilakis
    [containersNodeChildren release];
411 d8426ffb Miltiadis Vasilakis
    [containersNode release];
412 d8426ffb Miltiadis Vasilakis
    [accountNode release];
413 d8426ffb Miltiadis Vasilakis
    [rootNode release];
414 d8426ffb Miltiadis Vasilakis
    [pithos release];
415 d8426ffb Miltiadis Vasilakis
    [super dealloc];
416 d8426ffb Miltiadis Vasilakis
}
417 d8426ffb Miltiadis Vasilakis
418 d8426ffb Miltiadis Vasilakis
- (void)setPithos:(ASIPithos *)aPithos {
419 d8426ffb Miltiadis Vasilakis
    if (aPithos) {
420 d8426ffb Miltiadis Vasilakis
        if (![aPithos.authUser isEqualToString:pithos.authUser] || 
421 d8426ffb Miltiadis Vasilakis
            ![aPithos.authToken isEqualToString:pithos.authToken] || 
422 d8426ffb Miltiadis Vasilakis
            ![aPithos.storageURLPrefix isEqualToString:pithos.storageURLPrefix] ||
423 d8426ffb Miltiadis Vasilakis
            ![aPithos.publicURLPrefix isEqualToString:pithos.publicURLPrefix]) {
424 d8426ffb Miltiadis Vasilakis
            [self resetBrowser];
425 d8426ffb Miltiadis Vasilakis
            [pithos release];
426 d8426ffb Miltiadis Vasilakis
            pithos = [aPithos retain];
427 d8426ffb Miltiadis Vasilakis
            [self startBrowser];
428 d8426ffb Miltiadis Vasilakis
        } else {
429 d8426ffb Miltiadis Vasilakis
            [self startBrowser];
430 d8426ffb Miltiadis Vasilakis
        }
431 919cb043 Miltiadis Vasilakis
    }
432 e5fdf4d9 Miltiadis Vasilakis
}
433 e5fdf4d9 Miltiadis Vasilakis
434 d8426ffb Miltiadis Vasilakis
435 e5fdf4d9 Miltiadis Vasilakis
#pragma mark -
436 20f54e18 Miltiadis Vasilakis
#pragma mark Observers
437 e5fdf4d9 Miltiadis Vasilakis
438 e5fdf4d9 Miltiadis Vasilakis
- (void)pithosNodeChildrenUpdated:(NSNotification *)notification {
439 605c8932 Miltiadis Vasilakis
    PithosNode *node = (PithosNode *)[notification object];
440 af3b9f06 Miltiadis Vasilakis
    if (node == accountNode)
441 af3b9f06 Miltiadis Vasilakis
        return;
442 6a9b9f40 Miltiadis Vasilakis
    NSLog(@"pithosNodeChildrenUpdated:%@", node.url);
443 605c8932 Miltiadis Vasilakis
    NSInteger lastColumn = [browser lastColumn];
444 605c8932 Miltiadis Vasilakis
    for (NSInteger column = lastColumn; column >= 0; column--) {
445 605c8932 Miltiadis Vasilakis
        if ([[browser parentForItemsInColumn:column] isEqualTo:node]) {
446 605c8932 Miltiadis Vasilakis
            [browser reloadColumn:column];
447 605c8932 Miltiadis Vasilakis
            return;
448 605c8932 Miltiadis Vasilakis
        }
449 605c8932 Miltiadis Vasilakis
    }
450 e5fdf4d9 Miltiadis Vasilakis
}
451 e5fdf4d9 Miltiadis Vasilakis
452 4bf68b77 Miltiadis Vasilakis
- (void)pithosAccountNodeChildrenUpdated:(NSNotification *)notification {
453 4bf68b77 Miltiadis Vasilakis
    BOOL containerPithosFound = NO;
454 4bf68b77 Miltiadis Vasilakis
    BOOL containerTrashFound = NO;
455 20f54e18 Miltiadis Vasilakis
    NSMutableIndexSet *removedContainersNodeChildren = [NSMutableIndexSet indexSet];
456 20f54e18 Miltiadis Vasilakis
    for (NSUInteger i = 0 ; i < [containersNodeChildren count] ; i++) {
457 20f54e18 Miltiadis Vasilakis
        if (![accountNode.children containsObject:[containersNodeChildren objectAtIndex:i]])
458 20f54e18 Miltiadis Vasilakis
            [removedContainersNodeChildren addIndex:i];
459 20f54e18 Miltiadis Vasilakis
    }
460 20f54e18 Miltiadis Vasilakis
    [containersNodeChildren removeObjectsAtIndexes:removedContainersNodeChildren];
461 4bf68b77 Miltiadis Vasilakis
    for (PithosContainerNode *containerNode in accountNode.children) {
462 4bf68b77 Miltiadis Vasilakis
        if ([containerNode.pithosContainer.name isEqualToString:@"pithos"]) {
463 20f54e18 Miltiadis Vasilakis
            if (![containersNodeChildren containsObject:containerNode])
464 20f54e18 Miltiadis Vasilakis
                [containersNodeChildren insertObject:containerNode atIndex:0];
465 4bf68b77 Miltiadis Vasilakis
            containerPithosFound = YES;
466 4bf68b77 Miltiadis Vasilakis
        } else if ([containerNode.pithosContainer.name isEqualToString:@"trash"]) {
467 4bf68b77 Miltiadis Vasilakis
            NSUInteger insertIndex = 1;
468 4bf68b77 Miltiadis Vasilakis
            if (!containerPithosFound)
469 4bf68b77 Miltiadis Vasilakis
                insertIndex = 0;
470 20f54e18 Miltiadis Vasilakis
            if (![containersNodeChildren containsObject:containerNode])
471 20f54e18 Miltiadis Vasilakis
                [containersNodeChildren insertObject:containerNode atIndex:insertIndex];
472 4bf68b77 Miltiadis Vasilakis
            containerTrashFound = YES;
473 20f54e18 Miltiadis Vasilakis
        } else if (![containersNodeChildren containsObject:containerNode]) {
474 20f54e18 Miltiadis Vasilakis
            [containersNodeChildren addObject:containerNode];
475 4bf68b77 Miltiadis Vasilakis
        }
476 4bf68b77 Miltiadis Vasilakis
    }
477 4bf68b77 Miltiadis Vasilakis
    BOOL refreshAccountNode = NO;
478 4bf68b77 Miltiadis Vasilakis
    if (!containerPithosFound) {
479 4ae10a2b Miltiadis Vasilakis
        // Create pithos node
480 919cb043 Miltiadis Vasilakis
        ASIPithosContainerRequest *containerRequest = [ASIPithosContainerRequest createOrUpdateContainerRequestWithPithos:pithos 
481 919cb043 Miltiadis Vasilakis
                                                                                                            containerName:@"pithos"];
482 d8426ffb Miltiadis Vasilakis
        ASINetworkQueue *networkQueue = [ASINetworkQueue queue];
483 d8426ffb Miltiadis Vasilakis
        [networkQueue go];
484 d8426ffb Miltiadis Vasilakis
        [networkQueue addOperations:[NSArray arrayWithObject:[PithosUtilities prepareRequest:containerRequest]] waitUntilFinished:YES];
485 4bf68b77 Miltiadis Vasilakis
        if ([containerRequest error]) {
486 d8426ffb Miltiadis Vasilakis
            dispatch_async(dispatch_get_main_queue(), ^{
487 d8426ffb Miltiadis Vasilakis
                [PithosUtilities httpRequestErrorAlertWithRequest:containerRequest];
488 d8426ffb Miltiadis Vasilakis
            });
489 4bf68b77 Miltiadis Vasilakis
        } else {
490 4bf68b77 Miltiadis Vasilakis
            refreshAccountNode = YES;
491 4bf68b77 Miltiadis Vasilakis
        }
492 4bf68b77 Miltiadis Vasilakis
    }
493 4bf68b77 Miltiadis Vasilakis
    if (!containerTrashFound) {
494 4ae10a2b Miltiadis Vasilakis
        // Create trash node
495 919cb043 Miltiadis Vasilakis
        ASIPithosContainerRequest *containerRequest = [ASIPithosContainerRequest createOrUpdateContainerRequestWithPithos:pithos 
496 919cb043 Miltiadis Vasilakis
                                                                                                            containerName:@"trash"];
497 d8426ffb Miltiadis Vasilakis
        ASINetworkQueue *networkQueue = [ASINetworkQueue queue];
498 d8426ffb Miltiadis Vasilakis
        [networkQueue go];
499 d8426ffb Miltiadis Vasilakis
        [networkQueue addOperations:[NSArray arrayWithObject:[PithosUtilities prepareRequest:containerRequest]] waitUntilFinished:YES];
500 4bf68b77 Miltiadis Vasilakis
        if ([containerRequest error]) {
501 d8426ffb Miltiadis Vasilakis
            dispatch_async(dispatch_get_main_queue(), ^{
502 d8426ffb Miltiadis Vasilakis
                [PithosUtilities httpRequestErrorAlertWithRequest:containerRequest];
503 d8426ffb Miltiadis Vasilakis
            });
504 4bf68b77 Miltiadis Vasilakis
        } else {
505 4bf68b77 Miltiadis Vasilakis
            refreshAccountNode = YES;
506 4bf68b77 Miltiadis Vasilakis
        }
507 4bf68b77 Miltiadis Vasilakis
    }
508 20f54e18 Miltiadis Vasilakis
    
509 20f54e18 Miltiadis Vasilakis
    if (refreshAccountNode)
510 4ae10a2b Miltiadis Vasilakis
        [accountNode refresh];
511 20f54e18 Miltiadis Vasilakis
    
512 20f54e18 Miltiadis Vasilakis
    [outlineView reloadData];
513 20f54e18 Miltiadis Vasilakis
    
514 20f54e18 Miltiadis Vasilakis
    // Expand the folder outline view
515 20f54e18 Miltiadis Vasilakis
    [outlineView expandItem:nil expandChildren:YES];
516 20f54e18 Miltiadis Vasilakis
    
517 d8426ffb Miltiadis Vasilakis
    if (((rootNode == nil) || (rootNode == containersNode) || (rootNode == sharedNode)) && [containersNodeChildren count]) {
518 20f54e18 Miltiadis Vasilakis
        rootNode = [containersNodeChildren objectAtIndex:0];
519 20f54e18 Miltiadis Vasilakis
        [browser loadColumnZero];
520 4bf68b77 Miltiadis Vasilakis
    }
521 20f54e18 Miltiadis Vasilakis
    
522 20f54e18 Miltiadis Vasilakis
    if (notification)
523 20f54e18 Miltiadis Vasilakis
        [self refresh:nil];
524 20f54e18 Miltiadis Vasilakis
}
525 20f54e18 Miltiadis Vasilakis
526 20f54e18 Miltiadis Vasilakis
- (void)pithosBrowserRefreshNeeded:(NSNotification *)notification {
527 20f54e18 Miltiadis Vasilakis
    [self refresh:nil];
528 4bf68b77 Miltiadis Vasilakis
}
529 4bf68b77 Miltiadis Vasilakis
530 e5fdf4d9 Miltiadis Vasilakis
#pragma mark -
531 20f54e18 Miltiadis Vasilakis
#pragma mark Actions
532 e5fdf4d9 Miltiadis Vasilakis
533 1b1e6fa1 Miltiadis Vasilakis
- (IBAction)forceRefresh:(id)sender {
534 1b1e6fa1 Miltiadis Vasilakis
    if (sender)
535 1b1e6fa1 Miltiadis Vasilakis
        [accountNode forceRefresh];
536 1b1e6fa1 Miltiadis Vasilakis
    for (NSInteger column = [browser lastColumn]; column >= 0; column--) {
537 1b1e6fa1 Miltiadis Vasilakis
        PithosNode *node = (PithosNode *)[browser parentForItemsInColumn:column];
538 1b1e6fa1 Miltiadis Vasilakis
        node.forcedRefresh = YES;
539 1b1e6fa1 Miltiadis Vasilakis
        [(PithosNode *)[browser parentForItemsInColumn:column] invalidateChildren];                      
540 1b1e6fa1 Miltiadis Vasilakis
    }
541 1b1e6fa1 Miltiadis Vasilakis
    [browser validateVisibleColumns];
542 1b1e6fa1 Miltiadis Vasilakis
}
543 1b1e6fa1 Miltiadis Vasilakis
544 e5fdf4d9 Miltiadis Vasilakis
- (IBAction)refresh:(id)sender {
545 90fadc45 Miltiadis Vasilakis
    if ([[NSApp currentEvent] modifierFlags] & NSShiftKeyMask) {
546 1b1e6fa1 Miltiadis Vasilakis
        [self forceRefresh:sender];
547 90fadc45 Miltiadis Vasilakis
    } else {
548 90fadc45 Miltiadis Vasilakis
        if (sender)
549 90fadc45 Miltiadis Vasilakis
            [accountNode refresh];
550 90fadc45 Miltiadis Vasilakis
        for (NSInteger column = [browser lastColumn]; column >= 0; column--) {
551 90fadc45 Miltiadis Vasilakis
            [(PithosNode *)[browser parentForItemsInColumn:column] invalidateChildren];
552 90fadc45 Miltiadis Vasilakis
        }
553 1b1e6fa1 Miltiadis Vasilakis
        [browser validateVisibleColumns];
554 605c8932 Miltiadis Vasilakis
    }
555 e5fdf4d9 Miltiadis Vasilakis
}
556 e5fdf4d9 Miltiadis Vasilakis
557 e5fdf4d9 Miltiadis Vasilakis
#pragma mark -
558 20f54e18 Miltiadis Vasilakis
#pragma mark NSBrowserDelegate
559 e5fdf4d9 Miltiadis Vasilakis
560 e5fdf4d9 Miltiadis Vasilakis
- (id)rootItemForBrowser:(NSBrowser *)browser {
561 e5fdf4d9 Miltiadis Vasilakis
    return rootNode;    
562 e5fdf4d9 Miltiadis Vasilakis
}
563 e5fdf4d9 Miltiadis Vasilakis
564 e5fdf4d9 Miltiadis Vasilakis
- (NSInteger)browser:(NSBrowser *)browser numberOfChildrenOfItem:(id)item {
565 e5fdf4d9 Miltiadis Vasilakis
    PithosNode *node = (PithosNode *)item;
566 e5fdf4d9 Miltiadis Vasilakis
    return node.children.count;
567 e5fdf4d9 Miltiadis Vasilakis
}
568 e5fdf4d9 Miltiadis Vasilakis
569 e5fdf4d9 Miltiadis Vasilakis
- (id)browser:(NSBrowser *)browser child:(NSInteger)index ofItem:(id)item {
570 e5fdf4d9 Miltiadis Vasilakis
    PithosNode *node = (PithosNode *)item;
571 e5fdf4d9 Miltiadis Vasilakis
    return [node.children objectAtIndex:index];
572 e5fdf4d9 Miltiadis Vasilakis
}
573 e5fdf4d9 Miltiadis Vasilakis
574 e5fdf4d9 Miltiadis Vasilakis
- (BOOL)browser:(NSBrowser *)browser isLeafItem:(id)item {
575 e5fdf4d9 Miltiadis Vasilakis
    PithosNode *node = (PithosNode *)item;
576 e5fdf4d9 Miltiadis Vasilakis
    return node.isLeafItem;
577 e5fdf4d9 Miltiadis Vasilakis
}
578 e5fdf4d9 Miltiadis Vasilakis
579 e5fdf4d9 Miltiadis Vasilakis
- (id)browser:(NSBrowser *)browser objectValueForItem:(id)item {
580 e5fdf4d9 Miltiadis Vasilakis
    PithosNode *node = (PithosNode *)item;
581 e5fdf4d9 Miltiadis Vasilakis
    return node;
582 e5fdf4d9 Miltiadis Vasilakis
}
583 e5fdf4d9 Miltiadis Vasilakis
584 9f3a92de Miltiadis Vasilakis
- (NSViewController *)browser:(NSBrowser *)browser previewViewControllerForLeafItem:(id)item {
585 9f3a92de Miltiadis Vasilakis
    if (sharedPreviewController == nil)
586 9f3a92de Miltiadis Vasilakis
        sharedPreviewController = [[NSViewController alloc] initWithNibName:@"PithosBrowserPreviewController" bundle:[NSBundle bundleForClass:[self class]]];
587 9f3a92de Miltiadis Vasilakis
    return sharedPreviewController;
588 9f3a92de Miltiadis Vasilakis
}
589 9f3a92de Miltiadis Vasilakis
590 155f0dfd Miltiadis Vasilakis
//- (CGFloat)browser:(NSBrowser *)browser shouldSizeColumn:(NSInteger)columnIndex forUserResize:(BOOL)forUserResize toWidth:(CGFloat)suggestedWidth  {
591 155f0dfd Miltiadis Vasilakis
//    if (!forUserResize) {
592 155f0dfd Miltiadis Vasilakis
//        id item = [browser parentForItemsInColumn:columnIndex]; 
593 155f0dfd Miltiadis Vasilakis
//        if ([self browser:browser isLeafItem:item]) {
594 155f0dfd Miltiadis Vasilakis
//            suggestedWidth = 200; 
595 155f0dfd Miltiadis Vasilakis
//        }
596 155f0dfd Miltiadis Vasilakis
//    }
597 155f0dfd Miltiadis Vasilakis
//    return suggestedWidth;
598 155f0dfd Miltiadis Vasilakis
//}
599 9f3a92de Miltiadis Vasilakis
600 605c8932 Miltiadis Vasilakis
- (BOOL)browser:(NSBrowser *)sender isColumnValid:(NSInteger)column {
601 605c8932 Miltiadis Vasilakis
    return NO;
602 605c8932 Miltiadis Vasilakis
}
603 605c8932 Miltiadis Vasilakis
604 19c353fe Miltiadis Vasilakis
#pragma mark Editing
605 19c353fe Miltiadis Vasilakis
606 19c353fe Miltiadis Vasilakis
- (BOOL)browser:(NSBrowser *)browser shouldEditItem:(id)item {
607 4ae10a2b Miltiadis Vasilakis
    PithosNode *node = (PithosNode *)item;
608 af3b9f06 Miltiadis Vasilakis
    if (node.shared || node.sharingAccount || 
609 af3b9f06 Miltiadis Vasilakis
        ([node class] == [PithosContainerNode class]) || ([node class] == [PithosAccountNode class]))
610 4ae10a2b Miltiadis Vasilakis
        return NO;
611 19c353fe Miltiadis Vasilakis
    return YES;
612 19c353fe Miltiadis Vasilakis
}
613 19c353fe Miltiadis Vasilakis
614 19c353fe Miltiadis Vasilakis
- (void)browser:(NSBrowser *)browser setObjectValue:(id)object forItem:(id)item {
615 19c353fe Miltiadis Vasilakis
    PithosNode *node = (PithosNode *)item;
616 19c353fe Miltiadis Vasilakis
    NSString *newName = (NSString *)object;
617 19c353fe Miltiadis Vasilakis
    NSUInteger newNameLength = [newName length];
618 19c353fe Miltiadis Vasilakis
    NSRange firstSlashRange = [newName rangeOfString:@"/"];
619 19c353fe Miltiadis Vasilakis
    if ((newNameLength == 0) || 
620 19c353fe Miltiadis Vasilakis
        ((firstSlashRange.length == 1) && (firstSlashRange.location != (newNameLength - 1))) || 
621 19c353fe Miltiadis Vasilakis
        ([newName isEqualToString:node.displayName])) {
622 19c353fe Miltiadis Vasilakis
        return;
623 19c353fe Miltiadis Vasilakis
    }
624 19c353fe Miltiadis Vasilakis
    if (([node class] == [PithosObjectNode class]) || 
625 1b1e6fa1 Miltiadis Vasilakis
        (([node class] == [PithosSubdirNode class]) && !node.pithosObject.subdir && [node.pithosObject.name hasSuffix:@"/"])) {
626 d8426ffb Miltiadis Vasilakis
        // Operation: Rename (move) an object or subdir/ node
627 d8426ffb Miltiadis Vasilakis
        __block NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
628 4c1c46fd Miltiadis Vasilakis
            NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
629 d8426ffb Miltiadis Vasilakis
            if (operation.isCancelled) {
630 d8426ffb Miltiadis Vasilakis
                [pool drain];
631 d8426ffb Miltiadis Vasilakis
                return;
632 d8426ffb Miltiadis Vasilakis
            }
633 19c353fe Miltiadis Vasilakis
            NSString *destinationObjectName = [[node.pithosObject.name stringByDeletingLastPathComponent] stringByAppendingPathComponent:newName];
634 19c353fe Miltiadis Vasilakis
            if ([newName hasSuffix:@"/"])
635 19c353fe Miltiadis Vasilakis
                destinationObjectName = [destinationObjectName stringByAppendingString:@"/"];
636 19c353fe Miltiadis Vasilakis
            NSError *error = nil;
637 19c353fe Miltiadis Vasilakis
            BOOL isDirectory;
638 919cb043 Miltiadis Vasilakis
            if ([PithosUtilities objectExistsAtPithos:pithos 
639 919cb043 Miltiadis Vasilakis
                                        containerName:node.pithosContainer.name 
640 919cb043 Miltiadis Vasilakis
                                           objectName:destinationObjectName 
641 919cb043 Miltiadis Vasilakis
                                                error:&error 
642 919cb043 Miltiadis Vasilakis
                                          isDirectory:&isDirectory 
643 919cb043 Miltiadis Vasilakis
                                       sharingAccount:nil]) {
644 d8426ffb Miltiadis Vasilakis
                dispatch_async(dispatch_get_main_queue(), ^{
645 d8426ffb Miltiadis Vasilakis
                    NSAlert *alert = [[[NSAlert alloc] init] autorelease];
646 d8426ffb Miltiadis Vasilakis
                    [alert setMessageText:@"Name Taken"];
647 d8426ffb Miltiadis Vasilakis
                    [alert setInformativeText:[NSString stringWithFormat:@"The name '%@' is already taken. Please choose a different name", newName]];
648 d8426ffb Miltiadis Vasilakis
                    [alert addButtonWithTitle:@"OK"];
649 d8426ffb Miltiadis Vasilakis
                    [alert runModal];
650 d8426ffb Miltiadis Vasilakis
                });
651 4c1c46fd Miltiadis Vasilakis
                [pool drain];
652 19c353fe Miltiadis Vasilakis
                return;
653 19c353fe Miltiadis Vasilakis
            } else if (error) {
654 4c1c46fd Miltiadis Vasilakis
                [pool drain];
655 19c353fe Miltiadis Vasilakis
                return;
656 19c353fe Miltiadis Vasilakis
            }
657 d8426ffb Miltiadis Vasilakis
            if (operation.isCancelled) {
658 d8426ffb Miltiadis Vasilakis
                [pool drain];
659 d8426ffb Miltiadis Vasilakis
                return;
660 d8426ffb Miltiadis Vasilakis
            }
661 919cb043 Miltiadis Vasilakis
            ASIPithosObjectRequest *objectRequest = [PithosUtilities moveObjectRequestWithPithos:pithos 
662 919cb043 Miltiadis Vasilakis
                                                                                   containerName:node.pithosContainer.name 
663 919cb043 Miltiadis Vasilakis
                                                                                      objectName:node.pithosObject.name 
664 919cb043 Miltiadis Vasilakis
                                                                        destinationContainerName:node.pithosContainer.name 
665 919cb043 Miltiadis Vasilakis
                                                                           destinationObjectName:destinationObjectName 
666 919cb043 Miltiadis Vasilakis
                                                                                   checkIfExists:NO];
667 d8426ffb Miltiadis Vasilakis
            if (!operation.isCancelled && objectRequest) {
668 19c353fe Miltiadis Vasilakis
                objectRequest.delegate = self;
669 4c1c46fd Miltiadis Vasilakis
                objectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
670 4c1c46fd Miltiadis Vasilakis
                objectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
671 4c1c46fd Miltiadis Vasilakis
                NSString *messagePrefix = [NSString stringWithFormat:@"Moving '%@/%@' to '%@/%@'", 
672 4c1c46fd Miltiadis Vasilakis
                                           [objectRequest.userInfo objectForKey:@"sourceContainerName"], 
673 4c1c46fd Miltiadis Vasilakis
                                           [objectRequest.userInfo objectForKey:@"sourceObjectName"], 
674 4c1c46fd Miltiadis Vasilakis
                                           [objectRequest.userInfo objectForKey:@"destinationContainerName"], 
675 4c1c46fd Miltiadis Vasilakis
                                           [objectRequest.userInfo objectForKey:@"destinationObjectName"]];
676 1b1e6fa1 Miltiadis Vasilakis
                PithosActivity *activity = [activityFacility startActivityWithType:PithosActivityMove 
677 4c1c46fd Miltiadis Vasilakis
                                                                           message:messagePrefix];
678 1b1e6fa1 Miltiadis Vasilakis
                [(NSMutableDictionary *)(objectRequest.userInfo) addEntriesFromDictionary:
679 1b1e6fa1 Miltiadis Vasilakis
                 [NSDictionary dictionaryWithObjectsAndKeys:
680 1b1e6fa1 Miltiadis Vasilakis
                  [NSArray arrayWithObject:node.parent], @"forceRefreshNodes", 
681 1b1e6fa1 Miltiadis Vasilakis
                  [NSNumber numberWithBool:YES], @"refresh", 
682 1b1e6fa1 Miltiadis Vasilakis
                  activity, @"activity", 
683 4c1c46fd Miltiadis Vasilakis
                  [messagePrefix stringByAppendingString:@" (stopped)"], @"stoppedActivityMessage", 
684 4c1c46fd Miltiadis Vasilakis
                  [messagePrefix stringByAppendingString:@" (failed)"], @"failedActivityMessage", 
685 4c1c46fd Miltiadis Vasilakis
                  [messagePrefix stringByAppendingString:@" (finished)"], @"finishedActivityMessage", 
686 4c1c46fd Miltiadis Vasilakis
                  [NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority", 
687 1b1e6fa1 Miltiadis Vasilakis
                  [NSNumber numberWithUnsignedInteger:10], @"retries", 
688 4c1c46fd Miltiadis Vasilakis
                  NSStringFromSelector(@selector(moveFinished:)), @"didFinishSelector", 
689 4c1c46fd Miltiadis Vasilakis
                  NSStringFromSelector(@selector(requestFailed:)), @"didFailSelector", 
690 4c1c46fd Miltiadis Vasilakis
                  moveNetworkQueue, @"networkQueue", 
691 d8426ffb Miltiadis Vasilakis
                  @"move", @"operationType", 
692 1b1e6fa1 Miltiadis Vasilakis
                  nil]];
693 4c1c46fd Miltiadis Vasilakis
                [moveNetworkQueue addOperation:[PithosUtilities prepareRequest:objectRequest priority:NSOperationQueuePriorityHigh]];
694 19c353fe Miltiadis Vasilakis
            }
695 4c1c46fd Miltiadis Vasilakis
            [pool drain];
696 d8426ffb Miltiadis Vasilakis
        }];
697 d8426ffb Miltiadis Vasilakis
        [moveQueue addOperation:operation];
698 19c353fe Miltiadis Vasilakis
    } else if ([node class] == [PithosSubdirNode class]) {
699 19c353fe Miltiadis Vasilakis
        if (firstSlashRange.length == 1)
700 19c353fe Miltiadis Vasilakis
            return;
701 d8426ffb Miltiadis Vasilakis
        // Operation: Rename (move) a subdir node and its descendants
702 d8426ffb Miltiadis Vasilakis
        // The resulting ASIPithosObjectRequests are chained through dependencies
703 d8426ffb Miltiadis Vasilakis
        __block NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
704 4c1c46fd Miltiadis Vasilakis
            NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
705 d8426ffb Miltiadis Vasilakis
            if (operation.isCancelled) {
706 d8426ffb Miltiadis Vasilakis
                [pool drain];
707 d8426ffb Miltiadis Vasilakis
                return;
708 d8426ffb Miltiadis Vasilakis
            }
709 19c353fe Miltiadis Vasilakis
            NSString *destinationObjectName = [[node.pithosObject.name stringByDeletingLastPathComponent] stringByAppendingPathComponent:newName];
710 19c353fe Miltiadis Vasilakis
            NSError *error = nil;
711 19c353fe Miltiadis Vasilakis
            BOOL isDirectory;
712 919cb043 Miltiadis Vasilakis
            if ([PithosUtilities objectExistsAtPithos:pithos 
713 919cb043 Miltiadis Vasilakis
                                        containerName:node.pithosContainer.name 
714 919cb043 Miltiadis Vasilakis
                                           objectName:destinationObjectName 
715 919cb043 Miltiadis Vasilakis
                                                error:&error 
716 919cb043 Miltiadis Vasilakis
                                          isDirectory:&isDirectory 
717 919cb043 Miltiadis Vasilakis
                                       sharingAccount:nil]) {
718 d8426ffb Miltiadis Vasilakis
                dispatch_async(dispatch_get_main_queue(), ^{
719 d8426ffb Miltiadis Vasilakis
                    NSAlert *alert = [[[NSAlert alloc] init] autorelease];
720 d8426ffb Miltiadis Vasilakis
                    [alert setMessageText:@"Name Taken"];
721 d8426ffb Miltiadis Vasilakis
                    [alert setInformativeText:[NSString stringWithFormat:@"The name '%@' is already taken. Please choose a different name", newName]];
722 d8426ffb Miltiadis Vasilakis
                    [alert addButtonWithTitle:@"OK"];
723 d8426ffb Miltiadis Vasilakis
                    [alert runModal];
724 d8426ffb Miltiadis Vasilakis
                });
725 4c1c46fd Miltiadis Vasilakis
                [pool drain];
726 19c353fe Miltiadis Vasilakis
                return;
727 19c353fe Miltiadis Vasilakis
            } else if (error) {
728 4c1c46fd Miltiadis Vasilakis
                [pool drain];
729 19c353fe Miltiadis Vasilakis
                return;
730 19c353fe Miltiadis Vasilakis
            }
731 d8426ffb Miltiadis Vasilakis
            if (operation.isCancelled) {
732 d8426ffb Miltiadis Vasilakis
                [pool drain];
733 d8426ffb Miltiadis Vasilakis
                return;
734 d8426ffb Miltiadis Vasilakis
            }
735 19c353fe Miltiadis Vasilakis
            if (node.pithosObject.subdir)
736 19c353fe Miltiadis Vasilakis
                destinationObjectName = [destinationObjectName stringByAppendingString:@"/"];
737 919cb043 Miltiadis Vasilakis
            NSArray *objectRequests = [PithosUtilities moveObjectRequestsForSubdirWithPithos:pithos 
738 919cb043 Miltiadis Vasilakis
                                                                               containerName:node.pithosContainer.name 
739 919cb043 Miltiadis Vasilakis
                                                                                  objectName:node.pithosObject.name 
740 919cb043 Miltiadis Vasilakis
                                                                    destinationContainerName:node.pithosContainer.name 
741 919cb043 Miltiadis Vasilakis
                                                                       destinationObjectName:destinationObjectName 
742 919cb043 Miltiadis Vasilakis
                                                                               checkIfExists:NO];
743 d8426ffb Miltiadis Vasilakis
            if (!operation.isCancelled && objectRequests) {
744 d8426ffb Miltiadis Vasilakis
                ASIPithosObjectRequest *previousObjectRequest = nil;
745 19c353fe Miltiadis Vasilakis
                for (ASIPithosObjectRequest *objectRequest in objectRequests) {
746 d8426ffb Miltiadis Vasilakis
                    if (operation.isCancelled) {
747 d8426ffb Miltiadis Vasilakis
                        [pool drain];
748 d8426ffb Miltiadis Vasilakis
                        return;
749 d8426ffb Miltiadis Vasilakis
                    }
750 19c353fe Miltiadis Vasilakis
                    objectRequest.delegate = self;
751 4c1c46fd Miltiadis Vasilakis
                    objectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
752 4c1c46fd Miltiadis Vasilakis
                    objectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
753 4c1c46fd Miltiadis Vasilakis
                    NSString *messagePrefix = [NSString stringWithFormat:@"Moving '%@/%@' to '%@/%@'", 
754 4c1c46fd Miltiadis Vasilakis
                                               [objectRequest.userInfo objectForKey:@"sourceContainerName"], 
755 4c1c46fd Miltiadis Vasilakis
                                               [objectRequest.userInfo objectForKey:@"sourceObjectName"], 
756 4c1c46fd Miltiadis Vasilakis
                                               [objectRequest.userInfo objectForKey:@"destinationContainerName"], 
757 4c1c46fd Miltiadis Vasilakis
                                               [objectRequest.userInfo objectForKey:@"destinationObjectName"]];
758 1b1e6fa1 Miltiadis Vasilakis
                    PithosActivity *activity = [activityFacility startActivityWithType:PithosActivityMove 
759 4c1c46fd Miltiadis Vasilakis
                                                                               message:messagePrefix];
760 1b1e6fa1 Miltiadis Vasilakis
                    [(NSMutableDictionary *)(objectRequest.userInfo) addEntriesFromDictionary:
761 1b1e6fa1 Miltiadis Vasilakis
                     [NSDictionary dictionaryWithObjectsAndKeys:
762 1b1e6fa1 Miltiadis Vasilakis
                      [NSArray arrayWithObject:node.parent], @"forceRefreshNodes", 
763 1b1e6fa1 Miltiadis Vasilakis
                      [NSNumber numberWithBool:YES], @"refresh", 
764 1b1e6fa1 Miltiadis Vasilakis
                      activity, @"activity", 
765 4c1c46fd Miltiadis Vasilakis
                      [messagePrefix stringByAppendingString:@" (stopped)"], @"stoppedActivityMessage", 
766 4c1c46fd Miltiadis Vasilakis
                      [messagePrefix stringByAppendingString:@" (failed)"], @"failedActivityMessage", 
767 4c1c46fd Miltiadis Vasilakis
                      [messagePrefix stringByAppendingString:@" (finished)"], @"finishedActivityMessage", 
768 4c1c46fd Miltiadis Vasilakis
                      [NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority", 
769 1b1e6fa1 Miltiadis Vasilakis
                      [NSNumber numberWithUnsignedInteger:10], @"retries", 
770 4c1c46fd Miltiadis Vasilakis
                      NSStringFromSelector(@selector(moveFinished:)), @"didFinishSelector", 
771 4c1c46fd Miltiadis Vasilakis
                      NSStringFromSelector(@selector(requestFailed:)), @"didFailSelector", 
772 4c1c46fd Miltiadis Vasilakis
                      moveNetworkQueue, @"networkQueue", 
773 d8426ffb Miltiadis Vasilakis
                      @"move", @"operationType", 
774 1b1e6fa1 Miltiadis Vasilakis
                      nil]];
775 d8426ffb Miltiadis Vasilakis
                    if (previousObjectRequest)
776 d8426ffb Miltiadis Vasilakis
                        [objectRequest addDependency:previousObjectRequest];
777 d8426ffb Miltiadis Vasilakis
                    previousObjectRequest = objectRequest;
778 4c1c46fd Miltiadis Vasilakis
                    [moveNetworkQueue addOperation:[PithosUtilities prepareRequest:objectRequest priority:NSOperationQueuePriorityHigh]];
779 19c353fe Miltiadis Vasilakis
                }
780 19c353fe Miltiadis Vasilakis
            }
781 4c1c46fd Miltiadis Vasilakis
            [pool drain];
782 d8426ffb Miltiadis Vasilakis
        }];
783 d8426ffb Miltiadis Vasilakis
        [moveQueue addOperation:operation];
784 19c353fe Miltiadis Vasilakis
    }
785 19c353fe Miltiadis Vasilakis
}
786 19c353fe Miltiadis Vasilakis
787 f2f50f78 Miltiadis Vasilakis
#pragma mark Drag and Drop source
788 6dc7e931 Miltiadis Vasilakis
789 4ae10a2b Miltiadis Vasilakis
- (BOOL)browser:(NSBrowser *)aBrowser canDragRowsWithIndexes:(NSIndexSet *)rowIndexes inColumn:(NSInteger)column 
790 4ae10a2b Miltiadis Vasilakis
      withEvent:(NSEvent *)event {
791 4ae10a2b Miltiadis Vasilakis
    NSIndexPath *baseIndexPath = [browser indexPathForColumn:column];
792 4ae10a2b Miltiadis Vasilakis
    __block BOOL result = YES;
793 4ae10a2b Miltiadis Vasilakis
    [rowIndexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop){
794 4ae10a2b Miltiadis Vasilakis
        PithosNode *node = [browser itemAtIndexPath:[baseIndexPath indexPathByAddingIndex:idx]];
795 3b22507d Miltiadis Vasilakis
        if (([node class] == [PithosContainerNode class]) || ([node class] == [PithosAccountNode class])) {
796 4ae10a2b Miltiadis Vasilakis
            result = NO;
797 4ae10a2b Miltiadis Vasilakis
            *stop = YES;
798 4ae10a2b Miltiadis Vasilakis
        }
799 4ae10a2b Miltiadis Vasilakis
    }];
800 4ae10a2b Miltiadis Vasilakis
    return result;
801 4ae10a2b Miltiadis Vasilakis
}
802 4ae10a2b Miltiadis Vasilakis
803 6dc7e931 Miltiadis Vasilakis
- (BOOL)browser:(NSBrowser *)aBrowser writeRowsWithIndexes:(NSIndexSet *)rowIndexes inColumn:(NSInteger)column 
804 6dc7e931 Miltiadis Vasilakis
   toPasteboard:(NSPasteboard *)pasteboard {
805 6dc7e931 Miltiadis Vasilakis
    NSMutableArray *propertyList = [NSMutableArray arrayWithCapacity:[rowIndexes count]];
806 d41b3577 Miltiadis Vasilakis
    NSMutableArray *nodes = [NSMutableArray arrayWithCapacity:[rowIndexes count]];
807 133b1f2d Miltiadis Vasilakis
    NSIndexPath *baseIndexPath = [browser indexPathForColumn:column];
808 133b1f2d Miltiadis Vasilakis
    [rowIndexes enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop){
809 133b1f2d Miltiadis Vasilakis
        PithosNode *node = [browser itemAtIndexPath:[baseIndexPath indexPathByAddingIndex:idx]];
810 6dc7e931 Miltiadis Vasilakis
        [propertyList addObject:[node.pithosObject.name pathExtension]];
811 d41b3577 Miltiadis Vasilakis
        [nodes addObject:node];
812 133b1f2d Miltiadis Vasilakis
    }];
813 6dc7e931 Miltiadis Vasilakis
814 6dc7e931 Miltiadis Vasilakis
    [pasteboard declareTypes:[NSArray arrayWithObject:NSFilesPromisePboardType] owner:self];
815 6dc7e931 Miltiadis Vasilakis
    [pasteboard setPropertyList:propertyList forType:NSFilesPromisePboardType];
816 d41b3577 Miltiadis Vasilakis
    self.draggedNodes = nodes;
817 d41b3577 Miltiadis Vasilakis
    self.draggedParentNode = [browser parentForItemsInColumn:column];
818 6dc7e931 Miltiadis Vasilakis
    return YES;
819 6dc7e931 Miltiadis Vasilakis
}
820 6dc7e931 Miltiadis Vasilakis
821 6dc7e931 Miltiadis Vasilakis
- (NSArray *)browser:(NSBrowser *)aBrowser namesOfPromisedFilesDroppedAtDestination:(NSURL *)dropDestination 
822 6dc7e931 Miltiadis Vasilakis
forDraggedRowsWithIndexes:(NSIndexSet *)rowIndexes inColumn:(NSInteger)column {
823 3b22507d Miltiadis Vasilakis
    NSMutableArray *names = [NSMutableArray arrayWithCapacity:[draggedNodes count]];
824 3b22507d Miltiadis Vasilakis
    for (PithosNode *node in draggedNodes) {        
825 6dc7e931 Miltiadis Vasilakis
        // If the node is a subdir ask if the whole tree should be downloaded
826 d7c03491 Miltiadis Vasilakis
        if ([node class] == [PithosSubdirNode class]) {
827 f2f50f78 Miltiadis Vasilakis
            NSAlert *alert = [[[NSAlert alloc] init] autorelease];
828 6dc7e931 Miltiadis Vasilakis
            [alert setMessageText:@"Download directory"];
829 6dc7e931 Miltiadis Vasilakis
            [alert setInformativeText:[NSString stringWithFormat:@"'%@' is a directory, do you want to download its contents?", node.displayName]];
830 6dc7e931 Miltiadis Vasilakis
            [alert addButtonWithTitle:@"OK"];
831 6dc7e931 Miltiadis Vasilakis
            [alert addButtonWithTitle:@"Cancel"];
832 6dc7e931 Miltiadis Vasilakis
            NSInteger choice = [alert runModal];
833 6dc7e931 Miltiadis Vasilakis
            if (choice == NSAlertFirstButtonReturn) {
834 d8426ffb Miltiadis Vasilakis
                // Operation: Download a subdir node and its descendants
835 d8426ffb Miltiadis Vasilakis
                // The resulting ASIPithosObjectRequests are chained through dependencies
836 d8426ffb Miltiadis Vasilakis
                __block NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
837 4c1c46fd Miltiadis Vasilakis
                    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
838 d8426ffb Miltiadis Vasilakis
                    if (operation.isCancelled) {
839 d8426ffb Miltiadis Vasilakis
                        [pool drain];
840 d8426ffb Miltiadis Vasilakis
                        return;
841 d8426ffb Miltiadis Vasilakis
                    }
842 919cb043 Miltiadis Vasilakis
                    NSArray *objectRequests = [PithosUtilities objectDataRequestsForSubdirWithPithos:pithos 
843 919cb043 Miltiadis Vasilakis
                                                                                       containerName:node.pithosContainer.name 
844 919cb043 Miltiadis Vasilakis
                                                                                          objectName:node.pithosObject.name 
845 919cb043 Miltiadis Vasilakis
                                                                                         toDirectory:[dropDestination path] 
846 919cb043 Miltiadis Vasilakis
                                                                                       checkIfExists:YES 
847 919cb043 Miltiadis Vasilakis
                                                                                      sharingAccount:node.sharingAccount];
848 d8426ffb Miltiadis Vasilakis
                    if (!operation.isCancelled && objectRequests) {
849 d8426ffb Miltiadis Vasilakis
                        ASIPithosObjectRequest *previousObjectRequest = nil;
850 1b1e6fa1 Miltiadis Vasilakis
                        for (__block ASIPithosObjectRequest *objectRequest in objectRequests) {
851 d8426ffb Miltiadis Vasilakis
                            if (operation.isCancelled) {
852 d8426ffb Miltiadis Vasilakis
                                [pool drain];
853 d8426ffb Miltiadis Vasilakis
                                return;
854 d8426ffb Miltiadis Vasilakis
                            }
855 4c1c46fd Miltiadis Vasilakis
                            [names addObject:[objectRequest.userInfo objectForKey:@"fileName"]];
856 1ca8da38 Miltiadis Vasilakis
                            objectRequest.delegate = self;
857 4c1c46fd Miltiadis Vasilakis
                            objectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
858 4c1c46fd Miltiadis Vasilakis
                            objectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
859 4c1c46fd Miltiadis Vasilakis
                            NSString *messagePrefix = [NSString stringWithFormat:@"Downloading '%@'", [objectRequest.userInfo objectForKey:@"fileName"]];
860 470e6f81 Miltiadis Vasilakis
                            PithosActivity *activity = [activityFacility startActivityWithType:PithosActivityDownload 
861 4c1c46fd Miltiadis Vasilakis
                                                                                       message:[messagePrefix stringByAppendingString:@" (0%)"]
862 470e6f81 Miltiadis Vasilakis
                                                                                    totalBytes:[[objectRequest.userInfo objectForKey:@"bytes"] unsignedIntegerValue] 
863 470e6f81 Miltiadis Vasilakis
                                                                                  currentBytes:0];
864 4c1c46fd Miltiadis Vasilakis
                            dispatch_async(dispatch_get_main_queue(), ^{
865 4c1c46fd Miltiadis Vasilakis
                                [activityFacility updateActivity:activity withMessage:activity.message];  
866 4c1c46fd Miltiadis Vasilakis
                            });
867 1b1e6fa1 Miltiadis Vasilakis
                            [(NSMutableDictionary *)objectRequest.userInfo addEntriesFromDictionary:
868 1b1e6fa1 Miltiadis Vasilakis
                             [NSDictionary dictionaryWithObjectsAndKeys:
869 1b1e6fa1 Miltiadis Vasilakis
                              activity, @"activity", 
870 4c1c46fd Miltiadis Vasilakis
                              [messagePrefix stringByAppendingString:@" (stopped)"], @"stoppedActivityMessage", 
871 4c1c46fd Miltiadis Vasilakis
                              [messagePrefix stringByAppendingString:@" (failed)"], @"failedActivityMessage", 
872 4c1c46fd Miltiadis Vasilakis
                              [messagePrefix stringByAppendingString:@" (100%)"], @"finishedActivityMessage", 
873 4c1c46fd Miltiadis Vasilakis
                              [NSNumber numberWithInteger:NSOperationQueuePriorityNormal], @"priority", 
874 1b1e6fa1 Miltiadis Vasilakis
                              [NSNumber numberWithUnsignedInteger:10], @"retries", 
875 4c1c46fd Miltiadis Vasilakis
                              NSStringFromSelector(@selector(downloadObjectFinished:)), @"didFinishSelector", 
876 4c1c46fd Miltiadis Vasilakis
                              NSStringFromSelector(@selector(requestFailed:)), @"didFailSelector", 
877 4c1c46fd Miltiadis Vasilakis
                              downloadNetworkQueue, @"networkQueue", 
878 d8426ffb Miltiadis Vasilakis
                              @"download", @"operationType", 
879 1b1e6fa1 Miltiadis Vasilakis
                              nil]];
880 1b1e6fa1 Miltiadis Vasilakis
                            [objectRequest setBytesReceivedBlock:^(unsigned long long size, unsigned long long total){
881 1b1e6fa1 Miltiadis Vasilakis
                                [activityFacility updateActivity:activity 
882 4c1c46fd Miltiadis Vasilakis
                                                     withMessage:[messagePrefix stringByAppendingFormat:@" (%.0f%%)", (activity.totalBytes ? (100*(activity.currentBytes + size + 0.0)/(activity.totalBytes + 0.0)) : 100)] 
883 1b1e6fa1 Miltiadis Vasilakis
                                                      totalBytes:activity.totalBytes 
884 1b1e6fa1 Miltiadis Vasilakis
                                                    currentBytes:(activity.currentBytes + size)];
885 1b1e6fa1 Miltiadis Vasilakis
                            }];
886 d8426ffb Miltiadis Vasilakis
                            if (previousObjectRequest)
887 d8426ffb Miltiadis Vasilakis
                                [objectRequest addDependency:previousObjectRequest];
888 d8426ffb Miltiadis Vasilakis
                            previousObjectRequest = objectRequest;
889 4c1c46fd Miltiadis Vasilakis
                            [downloadNetworkQueue addOperation:[PithosUtilities prepareRequest:objectRequest]];
890 1ca8da38 Miltiadis Vasilakis
                        }
891 6dc7e931 Miltiadis Vasilakis
                    }
892 4c1c46fd Miltiadis Vasilakis
                    [pool drain];
893 d8426ffb Miltiadis Vasilakis
                }];
894 d8426ffb Miltiadis Vasilakis
                [downloadQueue addOperation:operation];
895 6dc7e931 Miltiadis Vasilakis
            }
896 6dc7e931 Miltiadis Vasilakis
        } else {
897 d8426ffb Miltiadis Vasilakis
            // Operation: Download an object node
898 d8426ffb Miltiadis Vasilakis
            __block NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
899 4c1c46fd Miltiadis Vasilakis
                NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
900 d8426ffb Miltiadis Vasilakis
                if (operation.isCancelled) {
901 d8426ffb Miltiadis Vasilakis
                    [pool drain];
902 d8426ffb Miltiadis Vasilakis
                    return;
903 d8426ffb Miltiadis Vasilakis
                }
904 919cb043 Miltiadis Vasilakis
                __block ASIPithosObjectRequest *objectRequest = [PithosUtilities objectDataRequestWithPithos:pithos 
905 919cb043 Miltiadis Vasilakis
                                                                                               containerName:node.pithosContainer.name 
906 919cb043 Miltiadis Vasilakis
                                                                                                  objectName:node.pithosObject.name 
907 919cb043 Miltiadis Vasilakis
                                                                                                 toDirectory:[dropDestination path] 
908 919cb043 Miltiadis Vasilakis
                                                                                               checkIfExists:YES 
909 919cb043 Miltiadis Vasilakis
                                                                                              sharingAccount:node.sharingAccount];
910 d8426ffb Miltiadis Vasilakis
                if (!operation.isCancelled && objectRequest) {
911 4c1c46fd Miltiadis Vasilakis
                    [names addObject:[objectRequest.userInfo objectForKey:@"fileName"]];
912 4c1c46fd Miltiadis Vasilakis
                    objectRequest.delegate = self;
913 4c1c46fd Miltiadis Vasilakis
                    objectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
914 4c1c46fd Miltiadis Vasilakis
                    objectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
915 4c1c46fd Miltiadis Vasilakis
                    NSString *messagePrefix = [NSString stringWithFormat:@"Downloading '%@'", [objectRequest.userInfo objectForKey:@"fileName"]];
916 4c1c46fd Miltiadis Vasilakis
                    PithosActivity *activity = [activityFacility startActivityWithType:PithosActivityDownload 
917 4c1c46fd Miltiadis Vasilakis
                                                                               message:[messagePrefix stringByAppendingString:@" (0%)"]
918 4c1c46fd Miltiadis Vasilakis
                                                                            totalBytes:node.pithosObject.bytes 
919 4c1c46fd Miltiadis Vasilakis
                                                                          currentBytes:0];
920 4c1c46fd Miltiadis Vasilakis
                    dispatch_async(dispatch_get_main_queue(), ^{
921 4c1c46fd Miltiadis Vasilakis
                        [activityFacility updateActivity:activity withMessage:activity.message];  
922 4c1c46fd Miltiadis Vasilakis
                    });
923 4c1c46fd Miltiadis Vasilakis
                    [(NSMutableDictionary *)objectRequest.userInfo addEntriesFromDictionary:
924 4c1c46fd Miltiadis Vasilakis
                     [NSDictionary dictionaryWithObjectsAndKeys:
925 4c1c46fd Miltiadis Vasilakis
                      activity, @"activity", 
926 4c1c46fd Miltiadis Vasilakis
                      [messagePrefix stringByAppendingString:@" (stopped)"], @"stoppedActivityMessage", 
927 4c1c46fd Miltiadis Vasilakis
                      [messagePrefix stringByAppendingString:@" (failed)"], @"failedActivityMessage", 
928 4c1c46fd Miltiadis Vasilakis
                      [messagePrefix stringByAppendingString:@" (100%)"], @"finishedActivityMessage", 
929 4c1c46fd Miltiadis Vasilakis
                      [NSNumber numberWithInteger:NSOperationQueuePriorityNormal], @"priority", 
930 4c1c46fd Miltiadis Vasilakis
                      [NSNumber numberWithUnsignedInteger:10], @"retries", 
931 4c1c46fd Miltiadis Vasilakis
                      NSStringFromSelector(@selector(downloadObjectFinished:)), @"didFinishSelector", 
932 4c1c46fd Miltiadis Vasilakis
                      NSStringFromSelector(@selector(requestFailed:)), @"didFailSelector", 
933 4c1c46fd Miltiadis Vasilakis
                      downloadNetworkQueue, @"networkQueue", 
934 d8426ffb Miltiadis Vasilakis
                      @"download", @"operationType", 
935 4c1c46fd Miltiadis Vasilakis
                      nil]];
936 4c1c46fd Miltiadis Vasilakis
                    [objectRequest setBytesReceivedBlock:^(unsigned long long size, unsigned long long total){
937 4c1c46fd Miltiadis Vasilakis
                        [activityFacility updateActivity:activity 
938 4c1c46fd Miltiadis Vasilakis
                                             withMessage:[messagePrefix stringByAppendingFormat:@" (%.0f%%)", (activity.totalBytes ? (100*(activity.currentBytes + size + 0.0)/(activity.totalBytes + 0.0)) : 100)] 
939 4c1c46fd Miltiadis Vasilakis
                                              totalBytes:activity.totalBytes 
940 4c1c46fd Miltiadis Vasilakis
                                            currentBytes:(activity.currentBytes + size)];
941 4c1c46fd Miltiadis Vasilakis
                    }];
942 4c1c46fd Miltiadis Vasilakis
                    [downloadNetworkQueue addOperation:[PithosUtilities prepareRequest:objectRequest]];
943 4c1c46fd Miltiadis Vasilakis
                    [pool drain];
944 4c1c46fd Miltiadis Vasilakis
                }
945 d8426ffb Miltiadis Vasilakis
            }];
946 d8426ffb Miltiadis Vasilakis
            [downloadQueue addOperation:operation];
947 6dc7e931 Miltiadis Vasilakis
        }
948 3b22507d Miltiadis Vasilakis
    }
949 6dc7e931 Miltiadis Vasilakis
    return names;
950 6dc7e931 Miltiadis Vasilakis
}
951 6dc7e931 Miltiadis Vasilakis
952 f2f50f78 Miltiadis Vasilakis
#pragma mark Drag and Drop destination
953 f2f50f78 Miltiadis Vasilakis
954 f2f50f78 Miltiadis Vasilakis
- (NSDragOperation)browser:aBrowser 
955 f2f50f78 Miltiadis Vasilakis
              validateDrop:(id<NSDraggingInfo>)info 
956 f2f50f78 Miltiadis Vasilakis
               proposedRow:(NSInteger *)row 
957 f2f50f78 Miltiadis Vasilakis
                    column:(NSInteger *)column 
958 f2f50f78 Miltiadis Vasilakis
             dropOperation:(NSBrowserDropOperation *)dropOperation {
959 f2f50f78 Miltiadis Vasilakis
    NSDragOperation result = NSDragOperationNone;
960 6a9b9f40 Miltiadis Vasilakis
    if ([[[info draggingPasteboard] types] containsObject:NSFilenamesPboardType]) {
961 d41b3577 Miltiadis Vasilakis
        // For a drop above, the drop is redirected to the parent item
962 f2f50f78 Miltiadis Vasilakis
        if (*dropOperation == NSBrowserDropAbove)
963 f2f50f78 Miltiadis Vasilakis
            *row = -1;
964 f2f50f78 Miltiadis Vasilakis
        // Only allow dropping in folders
965 f2f50f78 Miltiadis Vasilakis
        if (*column != -1) {
966 af3b9f06 Miltiadis Vasilakis
            PithosNode *dropNode;
967 f2f50f78 Miltiadis Vasilakis
            if (*row != -1) {
968 d41b3577 Miltiadis Vasilakis
                // Check if the node is not a folder and if so redirect to the parent item
969 af3b9f06 Miltiadis Vasilakis
                dropNode = [browser itemAtRow:*row inColumn:*column];
970 6e5693f9 Miltiadis Vasilakis
                if ([dropNode class] == [PithosObjectNode class])
971 f2f50f78 Miltiadis Vasilakis
                    *row = -1;
972 33bf3856 Miltiadis Vasilakis
            }
973 af3b9f06 Miltiadis Vasilakis
            if (*row == -1)
974 af3b9f06 Miltiadis Vasilakis
                dropNode = [browser parentForItemsInColumn:*column];
975 af3b9f06 Miltiadis Vasilakis
            
976 6e5693f9 Miltiadis Vasilakis
            if (!dropNode.shared && 
977 6e5693f9 Miltiadis Vasilakis
                (!dropNode.sharingAccount || 
978 6e5693f9 Miltiadis Vasilakis
                 ([dropNode class] == [PithosSubdirNode class]) || 
979 6e5693f9 Miltiadis Vasilakis
                 ([dropNode class] == [PithosContainerNode class]))) {
980 af3b9f06 Miltiadis Vasilakis
                *dropOperation = NSBrowserDropOn;
981 af3b9f06 Miltiadis Vasilakis
                result = NSDragOperationCopy;
982 af3b9f06 Miltiadis Vasilakis
            }
983 f2f50f78 Miltiadis Vasilakis
        }
984 d41b3577 Miltiadis Vasilakis
    } else if ([[[info draggingPasteboard] types] containsObject:NSFilesPromisePboardType]) {
985 d41b3577 Miltiadis Vasilakis
        // For a drop above, the drop is redirected to the parent item
986 d41b3577 Miltiadis Vasilakis
        if (*dropOperation == NSBrowserDropAbove) 
987 d41b3577 Miltiadis Vasilakis
            *row = -1;
988 d41b3577 Miltiadis Vasilakis
        // Only allow dropping in folders
989 d41b3577 Miltiadis Vasilakis
        if (*column != -1) {
990 d41b3577 Miltiadis Vasilakis
            PithosNode *dropNode;
991 d41b3577 Miltiadis Vasilakis
            if (*row != -1) {
992 d41b3577 Miltiadis Vasilakis
                // Check if the node is not a folder and if so redirect to the parent item
993 d41b3577 Miltiadis Vasilakis
                dropNode = [browser itemAtRow:*row inColumn:*column];
994 6e5693f9 Miltiadis Vasilakis
                if ([dropNode class] == [PithosObjectNode class])
995 d41b3577 Miltiadis Vasilakis
                    *row = -1;
996 d41b3577 Miltiadis Vasilakis
            }
997 d41b3577 Miltiadis Vasilakis
            if (*row == -1)
998 d41b3577 Miltiadis Vasilakis
                dropNode = [browser parentForItemsInColumn:*column];
999 d41b3577 Miltiadis Vasilakis
            
1000 af3b9f06 Miltiadis Vasilakis
            if (!dropNode.shared && !dropNode.sharingAccount) {
1001 4ae10a2b Miltiadis Vasilakis
                if ([info draggingSourceOperationMask] & NSDragOperationMove) {
1002 4ae10a2b Miltiadis Vasilakis
                    // NSDragOperationCopy | NSDragOperationMove -> NSDragOperationMove
1003 4ae10a2b Miltiadis Vasilakis
                    if ((([dropNode class] == [PithosContainerNode class]) || 
1004 4ae10a2b Miltiadis Vasilakis
                         dropNode.pithosObject.subdir || 
1005 4ae10a2b Miltiadis Vasilakis
                         ![dropNode.pithosObject.name hasSuffix:@"/"]) && 
1006 4ae10a2b Miltiadis Vasilakis
                        ![dropNode isEqualTo:draggedParentNode]) { 
1007 4ae10a2b Miltiadis Vasilakis
    //                    ![dropNode isEqualTo:draggedParentNode] && 
1008 4ae10a2b Miltiadis Vasilakis
    //                    ![draggedNodes containsObject:dropNode]) {                
1009 4ae10a2b Miltiadis Vasilakis
                        result = NSDragOperationMove;
1010 4ae10a2b Miltiadis Vasilakis
                    }
1011 4ae10a2b Miltiadis Vasilakis
                } else if ([info draggingSourceOperationMask] & NSDragOperationCopy) {
1012 4ae10a2b Miltiadis Vasilakis
                    // NSDragOperationCopy (Option modifier) -> NSDragOperationCopy
1013 4ae10a2b Miltiadis Vasilakis
                    if (([dropNode class] == [PithosContainerNode class]) || 
1014 4ae10a2b Miltiadis Vasilakis
                        dropNode.pithosObject.subdir || 
1015 4ae10a2b Miltiadis Vasilakis
                        ![dropNode.pithosObject.name hasSuffix:@"/"]) { 
1016 4ae10a2b Miltiadis Vasilakis
                        result = NSDragOperationCopy;
1017 4ae10a2b Miltiadis Vasilakis
                    }
1018 d41b3577 Miltiadis Vasilakis
                }
1019 d41b3577 Miltiadis Vasilakis
            }
1020 d41b3577 Miltiadis Vasilakis
        }
1021 f2f50f78 Miltiadis Vasilakis
    }
1022 f2f50f78 Miltiadis Vasilakis
    return result;
1023 f2f50f78 Miltiadis Vasilakis
}
1024 f2f50f78 Miltiadis Vasilakis
1025 f2f50f78 Miltiadis Vasilakis
- (BOOL)browser:(NSBrowser *)aBrowser 
1026 f2f50f78 Miltiadis Vasilakis
     acceptDrop:(id<NSDraggingInfo>)info 
1027 f2f50f78 Miltiadis Vasilakis
          atRow:(NSInteger)row 
1028 f2f50f78 Miltiadis Vasilakis
         column:(NSInteger)column 
1029 f2f50f78 Miltiadis Vasilakis
  dropOperation:(NSBrowserDropOperation)dropOperation {
1030 d41b3577 Miltiadis Vasilakis
    if ([[[info draggingPasteboard] types] containsObject:NSFilenamesPboardType]) {
1031 d41b3577 Miltiadis Vasilakis
        NSArray *filenames = [[info draggingPasteboard] propertyListForType:NSFilenamesPboardType];
1032 d41b3577 Miltiadis Vasilakis
        NSLog(@"drag in operation: %lu filenames: %@", [info draggingSourceOperationMask], filenames);
1033 d41b3577 Miltiadis Vasilakis
        if ((column != -1) && (filenames != nil)) {
1034 1b1e6fa1 Miltiadis Vasilakis
            PithosNode *node;
1035 d41b3577 Miltiadis Vasilakis
            if (row != -1)
1036 d41b3577 Miltiadis Vasilakis
                node = [browser itemAtRow:row inColumn:column];
1037 d41b3577 Miltiadis Vasilakis
            else
1038 d41b3577 Miltiadis Vasilakis
                node = [browser parentForItemsInColumn:column];
1039 d41b3577 Miltiadis Vasilakis
            NSLog(@"drag in node: %@", node.url);
1040 67e3336f Miltiadis Vasilakis
            return [self uploadFiles:filenames toNode:node];
1041 67e3336f Miltiadis Vasilakis
        }
1042 67e3336f Miltiadis Vasilakis
    } else if ([[[info draggingPasteboard] types] containsObject:NSFilesPromisePboardType]) {
1043 67e3336f Miltiadis Vasilakis
        NSLog(@"drag local operation: %lu nodes: %@", [info draggingSourceOperationMask], draggedNodes);
1044 67e3336f Miltiadis Vasilakis
        if ((column != -1) && (draggedNodes != nil)) {
1045 1b1e6fa1 Miltiadis Vasilakis
            PithosNode *node;
1046 67e3336f Miltiadis Vasilakis
            if (row != -1)
1047 67e3336f Miltiadis Vasilakis
                node = [browser itemAtRow:row inColumn:column];
1048 d41b3577 Miltiadis Vasilakis
            else
1049 67e3336f Miltiadis Vasilakis
                node = [browser parentForItemsInColumn:column];
1050 67e3336f Miltiadis Vasilakis
            NSLog(@"drag local node: %@", node.url);
1051 67e3336f Miltiadis Vasilakis
            if ([info draggingSourceOperationMask] & NSDragOperationMove)
1052 67e3336f Miltiadis Vasilakis
                return [self moveNodes:draggedNodes toNode:node];
1053 67e3336f Miltiadis Vasilakis
            else if ([info draggingSourceOperationMask] & NSDragOperationCopy)
1054 67e3336f Miltiadis Vasilakis
                return [self copyNodes:draggedNodes toNode:node];
1055 67e3336f Miltiadis Vasilakis
        }
1056 67e3336f Miltiadis Vasilakis
    }
1057 67e3336f Miltiadis Vasilakis
    return NO;
1058 67e3336f Miltiadis Vasilakis
}
1059 67e3336f Miltiadis Vasilakis
1060 67e3336f Miltiadis Vasilakis
#pragma mark -
1061 67e3336f Miltiadis Vasilakis
#pragma mark Drag and Drop methods
1062 67e3336f Miltiadis Vasilakis
1063 67e3336f Miltiadis Vasilakis
- (BOOL)uploadFiles:(NSArray *)filenames toNode:(PithosNode *)destinationNode {
1064 67e3336f Miltiadis Vasilakis
    if (([destinationNode class] != [PithosSubdirNode class]) && ([destinationNode class] != [PithosContainerNode class]))
1065 67e3336f Miltiadis Vasilakis
        return NO;
1066 0224a49f Miltiadis Vasilakis
    NSFileManager *fileManager = [NSFileManager defaultManager];
1067 67e3336f Miltiadis Vasilakis
    NSString *containerName = [NSString stringWithString:destinationNode.pithosContainer.name];
1068 67e3336f Miltiadis Vasilakis
    NSString *objectNamePrefix;
1069 67e3336f Miltiadis Vasilakis
    if ([destinationNode class] == [PithosSubdirNode class])
1070 67e3336f Miltiadis Vasilakis
        objectNamePrefix = [NSString stringWithString:destinationNode.pithosObject.name];
1071 67e3336f Miltiadis Vasilakis
    else
1072 67e3336f Miltiadis Vasilakis
        objectNamePrefix = [NSString string];
1073 67e3336f Miltiadis Vasilakis
    if ((destinationNode.pithosContainer.blockHash == nil) || (destinationNode.pithosContainer.blockSize == 0)) {
1074 919cb043 Miltiadis Vasilakis
        ASIPithosContainerRequest *containerRequest = [ASIPithosContainerRequest containerMetadataRequestWithPithos:pithos 
1075 919cb043 Miltiadis Vasilakis
                                                                                                      containerName:containerName];
1076 d8426ffb Miltiadis Vasilakis
        ASINetworkQueue *networkQueue = [ASINetworkQueue queue];
1077 d8426ffb Miltiadis Vasilakis
        [networkQueue go];
1078 d8426ffb Miltiadis Vasilakis
        [networkQueue addOperations:[NSArray arrayWithObject:[PithosUtilities prepareRequest:containerRequest]] waitUntilFinished:YES];
1079 67e3336f Miltiadis Vasilakis
        if ([containerRequest error]) {
1080 1b1e6fa1 Miltiadis Vasilakis
            [PithosUtilities httpRequestErrorAlertWithRequest:containerRequest];
1081 67e3336f Miltiadis Vasilakis
            return NO;
1082 0224a49f Miltiadis Vasilakis
        } else if (containerRequest.responseStatusCode != 204) {
1083 1b1e6fa1 Miltiadis Vasilakis
            [PithosUtilities unexpectedResponseStatusAlertWithRequest:containerRequest];
1084 67e3336f Miltiadis Vasilakis
            return NO;
1085 67e3336f Miltiadis Vasilakis
        }
1086 67e3336f Miltiadis Vasilakis
        destinationNode.pithosContainer.blockHash = [containerRequest blockHash];
1087 67e3336f Miltiadis Vasilakis
        destinationNode.pithosContainer.blockSize = [containerRequest blockSize];
1088 67e3336f Miltiadis Vasilakis
    }    
1089 67e3336f Miltiadis Vasilakis
    NSUInteger blockSize = destinationNode.pithosContainer.blockSize;
1090 67e3336f Miltiadis Vasilakis
    NSString *blockHash = destinationNode.pithosContainer.blockHash;
1091 67e3336f Miltiadis Vasilakis
    
1092 67e3336f Miltiadis Vasilakis
    for (NSString *filePath in filenames) {
1093 67e3336f Miltiadis Vasilakis
        BOOL isDirectory;
1094 0224a49f Miltiadis Vasilakis
        if ([fileManager fileExistsAtPath:filePath isDirectory:&isDirectory]) {
1095 67e3336f Miltiadis Vasilakis
            if (!isDirectory) {
1096 67e3336f Miltiadis Vasilakis
                // Upload file
1097 67e3336f Miltiadis Vasilakis
                NSString *objectName = [objectNamePrefix stringByAppendingPathComponent:[filePath lastPathComponent]];
1098 d8426ffb Miltiadis Vasilakis
                // Operation: Upload a local file
1099 d8426ffb Miltiadis Vasilakis
                __block NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
1100 4c1c46fd Miltiadis Vasilakis
                    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1101 d8426ffb Miltiadis Vasilakis
                    if (operation.isCancelled) {
1102 d8426ffb Miltiadis Vasilakis
                        [pool drain];
1103 d8426ffb Miltiadis Vasilakis
                        return;
1104 d8426ffb Miltiadis Vasilakis
                    }
1105 67e3336f Miltiadis Vasilakis
                    NSError *error = nil;
1106 1b1e6fa1 Miltiadis Vasilakis
                    NSString *contentType = [PithosUtilities contentTypeOfFile:filePath error:&error];
1107 67e3336f Miltiadis Vasilakis
                    if (contentType == nil)
1108 67e3336f Miltiadis Vasilakis
                        contentType = @"application/octet-stream";
1109 67e3336f Miltiadis Vasilakis
                    if (error)
1110 67e3336f Miltiadis Vasilakis
                        NSLog(@"contentType detection error: %@", error);
1111 67e3336f Miltiadis Vasilakis
                    NSArray *hashes = nil;
1112 d8426ffb Miltiadis Vasilakis
                    if (operation.isCancelled) {
1113 d8426ffb Miltiadis Vasilakis
                        [pool drain];
1114 d8426ffb Miltiadis Vasilakis
                        return;
1115 d8426ffb Miltiadis Vasilakis
                    }
1116 919cb043 Miltiadis Vasilakis
                    ASIPithosObjectRequest *objectRequest = [PithosUtilities writeObjectDataRequestWithPithos:pithos 
1117 919cb043 Miltiadis Vasilakis
                                                                                                containerName:containerName 
1118 919cb043 Miltiadis Vasilakis
                                                                                                   objectName:objectName 
1119 919cb043 Miltiadis Vasilakis
                                                                                                  contentType:contentType 
1120 919cb043 Miltiadis Vasilakis
                                                                                                    blockSize:blockSize 
1121 919cb043 Miltiadis Vasilakis
                                                                                                    blockHash:blockHash 
1122 919cb043 Miltiadis Vasilakis
                                                                                                      forFile:filePath 
1123 919cb043 Miltiadis Vasilakis
                                                                                                checkIfExists:YES 
1124 919cb043 Miltiadis Vasilakis
                                                                                                       hashes:&hashes 
1125 919cb043 Miltiadis Vasilakis
                                                                                               sharingAccount:destinationNode.sharingAccount];
1126 d8426ffb Miltiadis Vasilakis
                    if (!operation.isCancelled && objectRequest) {
1127 67e3336f Miltiadis Vasilakis
                        objectRequest.delegate = self;
1128 4c1c46fd Miltiadis Vasilakis
                        objectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
1129 4c1c46fd Miltiadis Vasilakis
                        objectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
1130 4c1c46fd Miltiadis Vasilakis
                        NSString *messagePrefix = [NSString stringWithFormat:@"Uploading '%@'", [objectRequest.userInfo objectForKey:@"fileName"]];
1131 470e6f81 Miltiadis Vasilakis
                        PithosActivity *activity = [activityFacility startActivityWithType:PithosActivityUpload 
1132 4c1c46fd Miltiadis Vasilakis
                                                                                   message:[messagePrefix stringByAppendingString:@" (0%)"]
1133 4c1c46fd Miltiadis Vasilakis
                                                                                totalBytes:[[objectRequest.userInfo objectForKey:@"bytes"] unsignedIntegerValue]
1134 470e6f81 Miltiadis Vasilakis
                                                                              currentBytes:0];
1135 470e6f81 Miltiadis Vasilakis
                        [(NSMutableDictionary *)objectRequest.userInfo addEntriesFromDictionary:
1136 470e6f81 Miltiadis Vasilakis
                         [NSDictionary dictionaryWithObjectsAndKeys:
1137 470e6f81 Miltiadis Vasilakis
                          containerName, @"containerName", 
1138 470e6f81 Miltiadis Vasilakis
                          objectName, @"objectName", 
1139 470e6f81 Miltiadis Vasilakis
                          contentType, @"contentType", 
1140 470e6f81 Miltiadis Vasilakis
                          [NSNumber numberWithUnsignedInteger:blockSize], @"blockSize", 
1141 470e6f81 Miltiadis Vasilakis
                          blockHash, @"blockHash", 
1142 470e6f81 Miltiadis Vasilakis
                          filePath, @"filePath", 
1143 470e6f81 Miltiadis Vasilakis
                          hashes, @"hashes", 
1144 1b1e6fa1 Miltiadis Vasilakis
                          [NSArray arrayWithObject:destinationNode], @"refreshNodes", 
1145 1b1e6fa1 Miltiadis Vasilakis
                          [NSNumber numberWithBool:YES], @"refresh", 
1146 470e6f81 Miltiadis Vasilakis
                          [NSNumber numberWithUnsignedInteger:10], @"iteration", 
1147 470e6f81 Miltiadis Vasilakis
                          activity, @"activity", 
1148 4c1c46fd Miltiadis Vasilakis
                          [messagePrefix stringByAppendingString:@" (stopped)"], @"stoppedActivityMessage", 
1149 4c1c46fd Miltiadis Vasilakis
                          [messagePrefix stringByAppendingString:@" (failed)"], @"failedActivityMessage", 
1150 4c1c46fd Miltiadis Vasilakis
                          [messagePrefix stringByAppendingString:@" (100%)"], @"finishedActivityMessage", 
1151 4c1c46fd Miltiadis Vasilakis
                          [NSNumber numberWithInteger:NSOperationQueuePriorityNormal], @"priority", 
1152 1b1e6fa1 Miltiadis Vasilakis
                          [NSNumber numberWithUnsignedInteger:10], @"retries", 
1153 4c1c46fd Miltiadis Vasilakis
                          NSStringFromSelector(@selector(uploadObjectUsingHashMapFinished:)), @"didFinishSelector", 
1154 4c1c46fd Miltiadis Vasilakis
                          NSStringFromSelector(@selector(requestFailed:)), @"didFailSelector", 
1155 4c1c46fd Miltiadis Vasilakis
                          uploadNetworkQueue, @"networkQueue", 
1156 d8426ffb Miltiadis Vasilakis
                          @"upload", @"operationType", 
1157 470e6f81 Miltiadis Vasilakis
                          nil]];
1158 67e3336f Miltiadis Vasilakis
                        if (destinationNode.sharingAccount)
1159 470e6f81 Miltiadis Vasilakis
                            [(NSMutableDictionary *)objectRequest.userInfo setObject:destinationNode.sharingAccount forKey:@"sharingAccount"];
1160 4c1c46fd Miltiadis Vasilakis
                        [uploadNetworkQueue addOperation:[PithosUtilities prepareRequest:objectRequest]];
1161 67e3336f Miltiadis Vasilakis
                    }
1162 4c1c46fd Miltiadis Vasilakis
                    [pool drain];
1163 d8426ffb Miltiadis Vasilakis
                }];
1164 d8426ffb Miltiadis Vasilakis
                [uploadQueue addOperation:operation];
1165 67e3336f Miltiadis Vasilakis
            } else {
1166 67e3336f Miltiadis Vasilakis
                // Upload directory, confirm first
1167 67e3336f Miltiadis Vasilakis
                NSAlert *alert = [[[NSAlert alloc] init] autorelease];
1168 67e3336f Miltiadis Vasilakis
                [alert setMessageText:@"Upload directory"];
1169 67e3336f Miltiadis Vasilakis
                [alert setInformativeText:[NSString stringWithFormat:@"'%@' is a directory, do you want to upload it and its contents?", filePath]];
1170 67e3336f Miltiadis Vasilakis
                [alert addButtonWithTitle:@"OK"];
1171 67e3336f Miltiadis Vasilakis
                [alert addButtonWithTitle:@"Cancel"];
1172 67e3336f Miltiadis Vasilakis
                NSInteger choice = [alert runModal];
1173 67e3336f Miltiadis Vasilakis
                if (choice == NSAlertFirstButtonReturn) {
1174 67e3336f Miltiadis Vasilakis
                    NSString *objectName = [objectNamePrefix stringByAppendingPathComponent:[filePath lastPathComponent]];
1175 d8426ffb Miltiadis Vasilakis
                    // Operation: Upload a local directory and its descendants
1176 d8426ffb Miltiadis Vasilakis
                    // The resulting ASIPithosObjectRequests are chained through dependencies
1177 d8426ffb Miltiadis Vasilakis
                    __block NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
1178 4c1c46fd Miltiadis Vasilakis
                        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1179 d8426ffb Miltiadis Vasilakis
                        if (operation.isCancelled) {
1180 d8426ffb Miltiadis Vasilakis
                            [pool drain];
1181 d8426ffb Miltiadis Vasilakis
                            return;
1182 d8426ffb Miltiadis Vasilakis
                        }
1183 67e3336f Miltiadis Vasilakis
                        NSMutableArray *objectNames = nil;
1184 67e3336f Miltiadis Vasilakis
                        NSMutableArray *contentTypes = nil;
1185 67e3336f Miltiadis Vasilakis
                        NSMutableArray *filePaths = nil;
1186 67e3336f Miltiadis Vasilakis
                        NSMutableArray *hashesArrays = nil;
1187 67e3336f Miltiadis Vasilakis
                        NSMutableArray *directoryObjectRequests = nil;
1188 919cb043 Miltiadis Vasilakis
                        NSArray *objectRequests = [PithosUtilities writeObjectDataRequestsWithPithos:pithos 
1189 919cb043 Miltiadis Vasilakis
                                                                                       containerName:containerName 
1190 919cb043 Miltiadis Vasilakis
                                                                                          objectName:objectName 
1191 919cb043 Miltiadis Vasilakis
                                                                                           blockSize:blockSize 
1192 919cb043 Miltiadis Vasilakis
                                                                                           blockHash:blockHash 
1193 919cb043 Miltiadis Vasilakis
                                                                                        forDirectory:filePath 
1194 919cb043 Miltiadis Vasilakis
                                                                                       checkIfExists:YES 
1195 919cb043 Miltiadis Vasilakis
                                                                                         objectNames:&objectNames
1196 919cb043 Miltiadis Vasilakis
                                                                                        contentTypes:&contentTypes
1197 919cb043 Miltiadis Vasilakis
                                                                                           filePaths:&filePaths
1198 919cb043 Miltiadis Vasilakis
                                                                                        hashesArrays:&hashesArrays 
1199 919cb043 Miltiadis Vasilakis
                                                                             directoryObjectRequests:&directoryObjectRequests 
1200 919cb043 Miltiadis Vasilakis
                                                                                      sharingAccount:destinationNode.sharingAccount];
1201 d8426ffb Miltiadis Vasilakis
                        if (operation.isCancelled) {
1202 d8426ffb Miltiadis Vasilakis
                            [pool drain];
1203 d8426ffb Miltiadis Vasilakis
                            return;
1204 d8426ffb Miltiadis Vasilakis
                        }
1205 d8426ffb Miltiadis Vasilakis
                        ASIPithosObjectRequest *previousObjectRequest = nil;
1206 67e3336f Miltiadis Vasilakis
                        for (ASIPithosObjectRequest *objectRequest in directoryObjectRequests) {
1207 d8426ffb Miltiadis Vasilakis
                            if (operation.isCancelled) {
1208 d8426ffb Miltiadis Vasilakis
                                [pool drain];
1209 d8426ffb Miltiadis Vasilakis
                                return;
1210 d8426ffb Miltiadis Vasilakis
                            }
1211 67e3336f Miltiadis Vasilakis
                            objectRequest.delegate = self;
1212 4c1c46fd Miltiadis Vasilakis
                            objectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
1213 4c1c46fd Miltiadis Vasilakis
                            objectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
1214 4c1c46fd Miltiadis Vasilakis
                            NSString *messagePrefix = [NSString stringWithFormat:@"Creating directory '%@'", [objectRequest.userInfo objectForKey:@"fileName"]];
1215 212a7d57 Miltiadis Vasilakis
                            PithosActivity *activity = [activityFacility startActivityWithType:PithosActivityCreateDirectory 
1216 4c1c46fd Miltiadis Vasilakis
                                                                                       message:messagePrefix];
1217 212a7d57 Miltiadis Vasilakis
                            [(NSMutableDictionary *)objectRequest.userInfo addEntriesFromDictionary:
1218 212a7d57 Miltiadis Vasilakis
                             [NSDictionary dictionaryWithObjectsAndKeys:
1219 212a7d57 Miltiadis Vasilakis
                              [NSNumber numberWithBool:YES], @"refresh", 
1220 212a7d57 Miltiadis Vasilakis
                              activity, @"activity", 
1221 4c1c46fd Miltiadis Vasilakis
                              [messagePrefix stringByAppendingString:@" (stopped)"], @"stoppedActivityMessage", 
1222 4c1c46fd Miltiadis Vasilakis
                              [messagePrefix stringByAppendingString:@" (failed)"], @"failedActivityMessage", 
1223 4c1c46fd Miltiadis Vasilakis
                              [messagePrefix stringByAppendingString:@" (finished)"], @"finishedActivityMessage", 
1224 4c1c46fd Miltiadis Vasilakis
                              [NSNumber numberWithInteger:NSOperationQueuePriorityNormal], @"priority", 
1225 212a7d57 Miltiadis Vasilakis
                              [NSNumber numberWithUnsignedInteger:10], @"retries", 
1226 4c1c46fd Miltiadis Vasilakis
                              NSStringFromSelector(@selector(uploadDirectoryObjectFinished:)), @"didFinishSelector", 
1227 4c1c46fd Miltiadis Vasilakis
                              NSStringFromSelector(@selector(requestFailed:)), @"didFailSelector", 
1228 4c1c46fd Miltiadis Vasilakis
                              uploadNetworkQueue, @"networkQueue", 
1229 d8426ffb Miltiadis Vasilakis
                              @"upload", @"queue", 
1230 212a7d57 Miltiadis Vasilakis
                              nil]];
1231 d8426ffb Miltiadis Vasilakis
                            if (previousObjectRequest)
1232 d8426ffb Miltiadis Vasilakis
                                [objectRequest addDependency:previousObjectRequest];
1233 d8426ffb Miltiadis Vasilakis
                            previousObjectRequest = objectRequest;
1234 4c1c46fd Miltiadis Vasilakis
                            [uploadNetworkQueue addOperation:[PithosUtilities prepareRequest:objectRequest]];
1235 67e3336f Miltiadis Vasilakis
                        }
1236 d8426ffb Miltiadis Vasilakis
                        if (!operation.isCancelled && objectRequests) {
1237 67e3336f Miltiadis Vasilakis
                            for (NSUInteger i = 0 ; i < [objectRequests count] ; i++) {
1238 d8426ffb Miltiadis Vasilakis
                                if (operation.isCancelled) {
1239 d8426ffb Miltiadis Vasilakis
                                    [pool drain];
1240 d8426ffb Miltiadis Vasilakis
                                    return;
1241 d8426ffb Miltiadis Vasilakis
                                }
1242 67e3336f Miltiadis Vasilakis
                                ASIPithosObjectRequest *objectRequest = [objectRequests objectAtIndex:i];
1243 d41b3577 Miltiadis Vasilakis
                                objectRequest.delegate = self;
1244 4c1c46fd Miltiadis Vasilakis
                                objectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
1245 4c1c46fd Miltiadis Vasilakis
                                objectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
1246 4c1c46fd Miltiadis Vasilakis
                                NSString *messagePrefix = [NSString stringWithFormat:@"Uploading '%@'", [objectRequest.userInfo objectForKey:@"fileName"]];
1247 470e6f81 Miltiadis Vasilakis
                                PithosActivity *activity = [activityFacility startActivityWithType:PithosActivityUpload 
1248 4c1c46fd Miltiadis Vasilakis
                                                                                           message:[messagePrefix stringByAppendingString:@" (0%)"]
1249 4c1c46fd Miltiadis Vasilakis
                                                                                        totalBytes:[[objectRequest.userInfo objectForKey:@"bytes"] unsignedIntegerValue]
1250 470e6f81 Miltiadis Vasilakis
                                                                                      currentBytes:0];
1251 470e6f81 Miltiadis Vasilakis
                                [(NSMutableDictionary *)objectRequest.userInfo addEntriesFromDictionary:
1252 470e6f81 Miltiadis Vasilakis
                                 [NSDictionary dictionaryWithObjectsAndKeys:
1253 470e6f81 Miltiadis Vasilakis
                                  containerName, @"containerName", 
1254 470e6f81 Miltiadis Vasilakis
                                  [objectNames objectAtIndex:i], @"objectName", 
1255 470e6f81 Miltiadis Vasilakis
                                  [contentTypes objectAtIndex:i], @"contentType", 
1256 470e6f81 Miltiadis Vasilakis
                                  [NSNumber numberWithUnsignedInteger:blockSize], @"blockSize", 
1257 470e6f81 Miltiadis Vasilakis
                                  blockHash, @"blockHash", 
1258 470e6f81 Miltiadis Vasilakis
                                  [filePaths objectAtIndex:i], @"filePath", 
1259 470e6f81 Miltiadis Vasilakis
                                  [hashesArrays objectAtIndex:i], @"hashes", 
1260 1b1e6fa1 Miltiadis Vasilakis
                                  [NSNumber numberWithBool:YES], @"refresh", 
1261 470e6f81 Miltiadis Vasilakis
                                  [NSNumber numberWithUnsignedInteger:10], @"iteration", 
1262 470e6f81 Miltiadis Vasilakis
                                  activity, @"activity", 
1263 4c1c46fd Miltiadis Vasilakis
                                  [messagePrefix stringByAppendingString:@" (stopped)"], @"stoppedActivityMessage", 
1264 4c1c46fd Miltiadis Vasilakis
                                  [messagePrefix stringByAppendingString:@" (failed)"], @"failedActivityMessage", 
1265 4c1c46fd Miltiadis Vasilakis
                                  [messagePrefix stringByAppendingString:@" (100%)"], @"finishedActivityMessage", 
1266 4c1c46fd Miltiadis Vasilakis
                                  [NSNumber numberWithInteger:NSOperationQueuePriorityNormal], @"priority", 
1267 1b1e6fa1 Miltiadis Vasilakis
                                  [NSNumber numberWithUnsignedInteger:10], @"retries", 
1268 4c1c46fd Miltiadis Vasilakis
                                  NSStringFromSelector(@selector(uploadObjectUsingHashMapFinished:)), @"didFinishSelector", 
1269 4c1c46fd Miltiadis Vasilakis
                                  NSStringFromSelector(@selector(requestFailed:)), @"didFailSelector", 
1270 4c1c46fd Miltiadis Vasilakis
                                  uploadNetworkQueue, @"networkQueue", 
1271 d8426ffb Miltiadis Vasilakis
                                  @"upload", @"queue", 
1272 470e6f81 Miltiadis Vasilakis
                                  nil]];
1273 67e3336f Miltiadis Vasilakis
                                if (destinationNode.sharingAccount)
1274 470e6f81 Miltiadis Vasilakis
                                    [(NSMutableDictionary *)objectRequest.userInfo setObject:destinationNode.sharingAccount forKey:@"sharingAccount"];
1275 d8426ffb Miltiadis Vasilakis
                                if (previousObjectRequest)
1276 d8426ffb Miltiadis Vasilakis
                                    [objectRequest addDependency:previousObjectRequest];
1277 d8426ffb Miltiadis Vasilakis
                                previousObjectRequest = objectRequest;
1278 4c1c46fd Miltiadis Vasilakis
                                [uploadNetworkQueue addOperation:[PithosUtilities prepareRequest:objectRequest]];
1279 d41b3577 Miltiadis Vasilakis
                            }
1280 d41b3577 Miltiadis Vasilakis
                        }
1281 4c1c46fd Miltiadis Vasilakis
                        [pool drain];
1282 d8426ffb Miltiadis Vasilakis
                    }];
1283 d8426ffb Miltiadis Vasilakis
                    [uploadQueue addOperation:operation];
1284 d41b3577 Miltiadis Vasilakis
                }
1285 d41b3577 Miltiadis Vasilakis
            }
1286 d41b3577 Miltiadis Vasilakis
        }
1287 67e3336f Miltiadis Vasilakis
    }
1288 67e3336f Miltiadis Vasilakis
    return YES;
1289 67e3336f Miltiadis Vasilakis
}
1290 67e3336f Miltiadis Vasilakis
1291 67e3336f Miltiadis Vasilakis
- (BOOL)moveNodes:(NSArray *)nodes toNode:(PithosNode *)destinationNode {
1292 1b1e6fa1 Miltiadis Vasilakis
    if ((([destinationNode class] != [PithosSubdirNode class]) && ([destinationNode class] != [PithosContainerNode class])) ||
1293 1b1e6fa1 Miltiadis Vasilakis
        (([destinationNode class] == [PithosSubdirNode class]) && !destinationNode.pithosObject.subdir && [destinationNode.pithosObject.name hasSuffix:@"/"])) 
1294 67e3336f Miltiadis Vasilakis
        return NO;
1295 67e3336f Miltiadis Vasilakis
    NSString *containerName = [NSString stringWithString:destinationNode.pithosContainer.name];
1296 67e3336f Miltiadis Vasilakis
    NSString *objectNamePrefix;
1297 67e3336f Miltiadis Vasilakis
    if ([destinationNode class] == [PithosSubdirNode class])
1298 67e3336f Miltiadis Vasilakis
        objectNamePrefix = [NSString stringWithString:destinationNode.pithosObject.name];
1299 67e3336f Miltiadis Vasilakis
    else
1300 67e3336f Miltiadis Vasilakis
        objectNamePrefix = [NSString string];
1301 67e3336f Miltiadis Vasilakis
1302 67e3336f Miltiadis Vasilakis
    for (PithosNode *node in nodes) {
1303 67e3336f Miltiadis Vasilakis
        if (([node class] == [PithosObjectNode class]) || 
1304 1b1e6fa1 Miltiadis Vasilakis
            (([node class] == [PithosSubdirNode class]) && !node.pithosObject.subdir && [node.pithosObject.name hasSuffix:@"/"])) {
1305 d8426ffb Miltiadis Vasilakis
            // Operation: Move an object or subdir/ node
1306 d8426ffb Miltiadis Vasilakis
            __block NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
1307 4c1c46fd Miltiadis Vasilakis
                NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1308 d8426ffb Miltiadis Vasilakis
                if (operation.isCancelled) {
1309 d8426ffb Miltiadis Vasilakis
                    [pool drain];
1310 d8426ffb Miltiadis Vasilakis
                    return;
1311 d8426ffb Miltiadis Vasilakis
                }
1312 67e3336f Miltiadis Vasilakis
                NSString *destinationObjectName = [objectNamePrefix stringByAppendingPathComponent:node.displayName];
1313 67e3336f Miltiadis Vasilakis
                if ([node.pithosObject.name hasSuffix:@"/"])
1314 67e3336f Miltiadis Vasilakis
                    destinationObjectName = [destinationObjectName stringByAppendingString:@"/"];
1315 919cb043 Miltiadis Vasilakis
                ASIPithosObjectRequest *objectRequest = [PithosUtilities moveObjectRequestWithPithos:pithos 
1316 919cb043 Miltiadis Vasilakis
                                                                                       containerName:node.pithosContainer.name 
1317 919cb043 Miltiadis Vasilakis
                                                                                          objectName:node.pithosObject.name 
1318 919cb043 Miltiadis Vasilakis
                                                                            destinationContainerName:containerName 
1319 919cb043 Miltiadis Vasilakis
                                                                               destinationObjectName:destinationObjectName 
1320 919cb043 Miltiadis Vasilakis
                                                                                       checkIfExists:YES];
1321 d8426ffb Miltiadis Vasilakis
                if (!operation.isCancelled && objectRequest) {
1322 67e3336f Miltiadis Vasilakis
                    objectRequest.delegate = self;
1323 4c1c46fd Miltiadis Vasilakis
                    objectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
1324 4c1c46fd Miltiadis Vasilakis
                    objectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
1325 4c1c46fd Miltiadis Vasilakis
                    NSString *messagePrefix = [NSString stringWithFormat:@"Moving '%@/%@' to '%@/%@'", 
1326 4c1c46fd Miltiadis Vasilakis
                                               [objectRequest.userInfo objectForKey:@"sourceContainerName"], 
1327 4c1c46fd Miltiadis Vasilakis
                                               [objectRequest.userInfo objectForKey:@"sourceObjectName"], 
1328 4c1c46fd Miltiadis Vasilakis
                                               [objectRequest.userInfo objectForKey:@"destinationContainerName"], 
1329 4c1c46fd Miltiadis Vasilakis
                                               [objectRequest.userInfo objectForKey:@"destinationObjectName"]];
1330 1b1e6fa1 Miltiadis Vasilakis
                    PithosActivity *activity = [activityFacility startActivityWithType:PithosActivityMove 
1331 4c1c46fd Miltiadis Vasilakis
                                                                               message:messagePrefix];
1332 1b1e6fa1 Miltiadis Vasilakis
                    [(NSMutableDictionary *)(objectRequest.userInfo) addEntriesFromDictionary:
1333 1b1e6fa1 Miltiadis Vasilakis
                     [NSDictionary dictionaryWithObjectsAndKeys:
1334 1b1e6fa1 Miltiadis Vasilakis
                      [NSArray arrayWithObjects:node.parent, destinationNode, nil], @"forceRefreshNodes", 
1335 1b1e6fa1 Miltiadis Vasilakis
                      activity, @"activity", 
1336 4c1c46fd Miltiadis Vasilakis
                      [messagePrefix stringByAppendingString:@" (stopped)"], @"stoppedActivityMessage", 
1337 4c1c46fd Miltiadis Vasilakis
                      [messagePrefix stringByAppendingString:@" (failed)"], @"failedActivityMessage", 
1338 4c1c46fd Miltiadis Vasilakis
                      [messagePrefix stringByAppendingString:@" (finished)"], @"finishedActivityMessage", 
1339 4c1c46fd Miltiadis Vasilakis
                      [NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority", 
1340 1b1e6fa1 Miltiadis Vasilakis
                      [NSNumber numberWithUnsignedInteger:10], @"retries", 
1341 4c1c46fd Miltiadis Vasilakis
                      NSStringFromSelector(@selector(moveFinished:)), @"didFinishSelector", 
1342 4c1c46fd Miltiadis Vasilakis
                      NSStringFromSelector(@selector(requestFailed:)), @"didFailSelector", 
1343 4c1c46fd Miltiadis Vasilakis
                      moveNetworkQueue, @"networkQueue", 
1344 d8426ffb Miltiadis Vasilakis
                      @"move", @"operationType", 
1345 1b1e6fa1 Miltiadis Vasilakis
                      nil]];
1346 4c1c46fd Miltiadis Vasilakis
                    [moveNetworkQueue addOperation:[PithosUtilities prepareRequest:objectRequest priority:NSOperationQueuePriorityHigh]];
1347 67e3336f Miltiadis Vasilakis
                }
1348 4c1c46fd Miltiadis Vasilakis
                [pool drain];
1349 d8426ffb Miltiadis Vasilakis
            }];
1350 d8426ffb Miltiadis Vasilakis
            [moveQueue addOperation:operation];
1351 67e3336f Miltiadis Vasilakis
        } else if ([node class] == [PithosSubdirNode class]) {
1352 d8426ffb Miltiadis Vasilakis
            // Operation: Move a subdir node and its descendants
1353 d8426ffb Miltiadis Vasilakis
            // The resulting ASIPithosObjectRequests are chained through dependencies
1354 d8426ffb Miltiadis Vasilakis
            __block NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
1355 4c1c46fd Miltiadis Vasilakis
                NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1356 d8426ffb Miltiadis Vasilakis
                if (operation.isCancelled) {
1357 d8426ffb Miltiadis Vasilakis
                    [pool drain];
1358 d8426ffb Miltiadis Vasilakis
                    return;
1359 d8426ffb Miltiadis Vasilakis
                }
1360 67e3336f Miltiadis Vasilakis
                NSString *destinationObjectName = [objectNamePrefix stringByAppendingPathComponent:node.displayName];
1361 67e3336f Miltiadis Vasilakis
                if (node.pithosObject.subdir)
1362 67e3336f Miltiadis Vasilakis
                    destinationObjectName = [destinationObjectName stringByAppendingString:@"/"];
1363 919cb043 Miltiadis Vasilakis
                NSArray *objectRequests = [PithosUtilities moveObjectRequestsForSubdirWithPithos:pithos 
1364 919cb043 Miltiadis Vasilakis
                                                                                   containerName:node.pithosContainer.name 
1365 919cb043 Miltiadis Vasilakis
                                                                                      objectName:node.pithosObject.name 
1366 919cb043 Miltiadis Vasilakis
                                                                        destinationContainerName:containerName 
1367 919cb043 Miltiadis Vasilakis
                                                                           destinationObjectName:destinationObjectName 
1368 919cb043 Miltiadis Vasilakis
                                                                                   checkIfExists:YES];
1369 d8426ffb Miltiadis Vasilakis
                if (!operation.isCancelled && objectRequests) {
1370 d8426ffb Miltiadis Vasilakis
                    ASIPithosObjectRequest *previousObjectRequest = nil;
1371 67e3336f Miltiadis Vasilakis
                    for (ASIPithosObjectRequest *objectRequest in objectRequests) {
1372 d8426ffb Miltiadis Vasilakis
                        if (operation.isCancelled) {
1373 d8426ffb Miltiadis Vasilakis
                            [pool drain];
1374 d8426ffb Miltiadis Vasilakis
                            return;
1375 d8426ffb Miltiadis Vasilakis
                        }
1376 67e3336f Miltiadis Vasilakis
                        objectRequest.delegate = self;
1377 4c1c46fd Miltiadis Vasilakis
                        objectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
1378 4c1c46fd Miltiadis Vasilakis
                        objectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
1379 4c1c46fd Miltiadis Vasilakis
                        NSString *messagePrefix = [NSString stringWithFormat:@"Moving '%@/%@' to '%@/%@'", 
1380 4c1c46fd Miltiadis Vasilakis
                                                   [objectRequest.userInfo objectForKey:@"sourceContainerName"], 
1381 4c1c46fd Miltiadis Vasilakis
                                                   [objectRequest.userInfo objectForKey:@"sourceObjectName"], 
1382 4c1c46fd Miltiadis Vasilakis
                                                   [objectRequest.userInfo objectForKey:@"destinationContainerName"], 
1383 4c1c46fd Miltiadis Vasilakis
                                                   [objectRequest.userInfo objectForKey:@"destinationObjectName"]];
1384 1b1e6fa1 Miltiadis Vasilakis
                        PithosActivity *activity = [activityFacility startActivityWithType:PithosActivityMove 
1385 4c1c46fd Miltiadis Vasilakis
                                                                                   message:messagePrefix];
1386 1b1e6fa1 Miltiadis Vasilakis
                        [(NSMutableDictionary *)(objectRequest.userInfo) addEntriesFromDictionary:
1387 1b1e6fa1 Miltiadis Vasilakis
                         [NSDictionary dictionaryWithObjectsAndKeys:
1388 1b1e6fa1 Miltiadis Vasilakis
                          [NSArray arrayWithObjects:node.parent, destinationNode, nil], @"forceRefreshNodes", 
1389 1b1e6fa1 Miltiadis Vasilakis
                          [NSNumber numberWithBool:YES], @"refresh", 
1390 1b1e6fa1 Miltiadis Vasilakis
                          activity, @"activity", 
1391 4c1c46fd Miltiadis Vasilakis
                          [messagePrefix stringByAppendingString:@" (stopped)"], @"stoppedActivityMessage", 
1392 4c1c46fd Miltiadis Vasilakis
                          [messagePrefix stringByAppendingString:@" (failed)"], @"failedActivityMessage", 
1393 4c1c46fd Miltiadis Vasilakis
                          [messagePrefix stringByAppendingString:@" (finished)"], @"finishedActivityMessage", 
1394 4c1c46fd Miltiadis Vasilakis
                          [NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority", 
1395 1b1e6fa1 Miltiadis Vasilakis
                          [NSNumber numberWithUnsignedInteger:10], @"retries", 
1396 4c1c46fd Miltiadis Vasilakis
                          NSStringFromSelector(@selector(moveFinished:)), @"didFinishSelector", 
1397 4c1c46fd Miltiadis Vasilakis
                          NSStringFromSelector(@selector(requestFailed:)), @"didFailSelector", 
1398 4c1c46fd Miltiadis Vasilakis
                          moveNetworkQueue, @"networkQueue", 
1399 d8426ffb Miltiadis Vasilakis
                          @"move", @"operationType", 
1400 1b1e6fa1 Miltiadis Vasilakis
                          nil]];
1401 d8426ffb Miltiadis Vasilakis
                        if (previousObjectRequest)
1402 d8426ffb Miltiadis Vasilakis
                            [objectRequest addDependency:previousObjectRequest];
1403 d8426ffb Miltiadis Vasilakis
                        previousObjectRequest = objectRequest;
1404 4c1c46fd Miltiadis Vasilakis
                        [moveNetworkQueue addOperation:[PithosUtilities prepareRequest:objectRequest priority:NSOperationQueuePriorityHigh]];
1405 d41b3577 Miltiadis Vasilakis
                    }
1406 d41b3577 Miltiadis Vasilakis
                }
1407 4c1c46fd Miltiadis Vasilakis
                [pool drain];
1408 d8426ffb Miltiadis Vasilakis
            }];
1409 d8426ffb Miltiadis Vasilakis
            [moveQueue addOperation:operation];
1410 67e3336f Miltiadis Vasilakis
        }
1411 67e3336f Miltiadis Vasilakis
    }
1412 67e3336f Miltiadis Vasilakis
    return YES;
1413 67e3336f Miltiadis Vasilakis
}
1414 d41b3577 Miltiadis Vasilakis
1415 67e3336f Miltiadis Vasilakis
- (BOOL)copyNodes:(NSArray *)nodes toNode:(PithosNode *)destinationNode {    
1416 1b1e6fa1 Miltiadis Vasilakis
    if ((([destinationNode class] != [PithosSubdirNode class]) && ([destinationNode class] != [PithosContainerNode class])) ||
1417 1b1e6fa1 Miltiadis Vasilakis
        (([destinationNode class] == [PithosSubdirNode class]) && !destinationNode.pithosObject.subdir && [destinationNode.pithosObject.name hasSuffix:@"/"])) 
1418 67e3336f Miltiadis Vasilakis
        return NO;
1419 67e3336f Miltiadis Vasilakis
    NSString *containerName = [NSString stringWithString:destinationNode.pithosContainer.name];
1420 67e3336f Miltiadis Vasilakis
    NSString *objectNamePrefix;
1421 67e3336f Miltiadis Vasilakis
    if ([destinationNode class] == [PithosSubdirNode class])
1422 67e3336f Miltiadis Vasilakis
        objectNamePrefix = [NSString stringWithString:destinationNode.pithosObject.name];
1423 67e3336f Miltiadis Vasilakis
    else
1424 67e3336f Miltiadis Vasilakis
        objectNamePrefix = [NSString string];
1425 67e3336f Miltiadis Vasilakis
    
1426 67e3336f Miltiadis Vasilakis
    for (PithosNode *node in nodes) {
1427 67e3336f Miltiadis Vasilakis
        if (([node class] == [PithosObjectNode class]) || 
1428 1b1e6fa1 Miltiadis Vasilakis
            (([node class] == [PithosSubdirNode class]) && !node.pithosObject.subdir && [node.pithosObject.name hasSuffix:@"/"])) {
1429 d8426ffb Miltiadis Vasilakis
            // Operation: Copy an object or subdir/ node
1430 d8426ffb Miltiadis Vasilakis
            __block NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
1431 4c1c46fd Miltiadis Vasilakis
                NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1432 d8426ffb Miltiadis Vasilakis
                if (operation.isCancelled) {
1433 d8426ffb Miltiadis Vasilakis
                    [pool drain];
1434 d8426ffb Miltiadis Vasilakis
                    return;
1435 d8426ffb Miltiadis Vasilakis
                }
1436 67e3336f Miltiadis Vasilakis
                NSString *destinationObjectName;
1437 67e3336f Miltiadis Vasilakis
                if (![destinationNode isEqualTo:node.parent]) {
1438 67e3336f Miltiadis Vasilakis
                    destinationObjectName = [objectNamePrefix stringByAppendingPathComponent:node.displayName];
1439 67e3336f Miltiadis Vasilakis
                    if ([node.pithosObject.name hasSuffix:@"/"])
1440 67e3336f Miltiadis Vasilakis
                        destinationObjectName = [destinationObjectName stringByAppendingString:@"/"];
1441 67e3336f Miltiadis Vasilakis
                } else {
1442 919cb043 Miltiadis Vasilakis
                    destinationObjectName = [PithosUtilities safeObjectNameForPithos:pithos 
1443 919cb043 Miltiadis Vasilakis
                                                                       containerName:containerName 
1444 919cb043 Miltiadis Vasilakis
                                                                          objectName:node.pithosObject.name];
1445 67e3336f Miltiadis Vasilakis
                }
1446 d8426ffb Miltiadis Vasilakis
                if (operation.isCancelled) {
1447 d8426ffb Miltiadis Vasilakis
                    [pool drain];
1448 d8426ffb Miltiadis Vasilakis
                    return;
1449 d8426ffb Miltiadis Vasilakis
                }
1450 919cb043 Miltiadis Vasilakis
                ASIPithosObjectRequest *objectRequest = [PithosUtilities copyObjectRequestWithPithos:pithos 
1451 919cb043 Miltiadis Vasilakis
                                                                                       containerName:node.pithosContainer.name 
1452 919cb043 Miltiadis Vasilakis
                                                                                          objectName:node.pithosObject.name 
1453 919cb043 Miltiadis Vasilakis
                                                                            destinationContainerName:containerName 
1454 919cb043 Miltiadis Vasilakis
                                                                               destinationObjectName:destinationObjectName 
1455 919cb043 Miltiadis Vasilakis
                                                                                       checkIfExists:YES 
1456 919cb043 Miltiadis Vasilakis
                                                                                      sharingAccount:node.sharingAccount];
1457 d8426ffb Miltiadis Vasilakis
                if (!operation.isCancelled && objectRequest) {
1458 67e3336f Miltiadis Vasilakis
                    objectRequest.delegate = self;
1459 4c1c46fd Miltiadis Vasilakis
                    objectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
1460 4c1c46fd Miltiadis Vasilakis
                    objectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
1461 4c1c46fd Miltiadis Vasilakis
                    NSString *messagePrefix = [NSString stringWithFormat:@"Copying '%@/%@' to '%@/%@'", 
1462 4c1c46fd Miltiadis Vasilakis
                                               [objectRequest.userInfo objectForKey:@"sourceContainerName"], 
1463 4c1c46fd Miltiadis Vasilakis
                                               [objectRequest.userInfo objectForKey:@"sourceObjectName"], 
1464 4c1c46fd Miltiadis Vasilakis
                                               [objectRequest.userInfo objectForKey:@"destinationContainerName"], 
1465 4c1c46fd Miltiadis Vasilakis
                                               [objectRequest.userInfo objectForKey:@"destinationObjectName"]];
1466 1b1e6fa1 Miltiadis Vasilakis
                    PithosActivity *activity = [activityFacility startActivityWithType:PithosActivityCopy 
1467 4c1c46fd Miltiadis Vasilakis
                                                                               message:messagePrefix];
1468 1b1e6fa1 Miltiadis Vasilakis
                    [(NSMutableDictionary *)(objectRequest.userInfo) addEntriesFromDictionary:
1469 1b1e6fa1 Miltiadis Vasilakis
                     [NSDictionary dictionaryWithObjectsAndKeys:
1470 1b1e6fa1 Miltiadis Vasilakis
                      [NSArray arrayWithObject:destinationNode], @"forceRefreshNodes", 
1471 1b1e6fa1 Miltiadis Vasilakis
                      activity, @"activity", 
1472 4c1c46fd Miltiadis Vasilakis
                      [messagePrefix stringByAppendingString:@" (stopped)"], @"stoppedActivityMessage", 
1473 4c1c46fd Miltiadis Vasilakis
                      [messagePrefix stringByAppendingString:@" (failed)"], @"failedActivityMessage", 
1474 4c1c46fd Miltiadis Vasilakis
                      [messagePrefix stringByAppendingString:@" (finished)"], @"finishedActivityMessage", 
1475 4c1c46fd Miltiadis Vasilakis
                      [NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority", 
1476 1b1e6fa1 Miltiadis Vasilakis
                      [NSNumber numberWithUnsignedInteger:10], @"retries", 
1477 4c1c46fd Miltiadis Vasilakis
                      NSStringFromSelector(@selector(copyFinished:)), @"didFinishSelector", 
1478 4c1c46fd Miltiadis Vasilakis
                      NSStringFromSelector(@selector(requestFailed:)), @"didFailSelector", 
1479 4c1c46fd Miltiadis Vasilakis
                      copyNetworkQueue, @"networkQueue", 
1480 d8426ffb Miltiadis Vasilakis
                      @"copy", @"operationType", 
1481 1b1e6fa1 Miltiadis Vasilakis
                      nil]];
1482 4c1c46fd Miltiadis Vasilakis
                    [copyNetworkQueue addOperation:[PithosUtilities prepareRequest:objectRequest priority:NSOperationQueuePriorityHigh]];
1483 67e3336f Miltiadis Vasilakis
                }
1484 4c1c46fd Miltiadis Vasilakis
                [pool drain];
1485 d8426ffb Miltiadis Vasilakis
            }];
1486 d8426ffb Miltiadis Vasilakis
            [copyQueue addOperation:operation];
1487 67e3336f Miltiadis Vasilakis
        } else if ([node class] == [PithosSubdirNode class]) {
1488 d8426ffb Miltiadis Vasilakis
            // Operation: Copy a subdir node and its descendants
1489 d8426ffb Miltiadis Vasilakis
            // The resulting ASIPithosObjectRequests are chained through dependencies
1490 d8426ffb Miltiadis Vasilakis
            __block NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
1491 4c1c46fd Miltiadis Vasilakis
                NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1492 d8426ffb Miltiadis Vasilakis
                if (operation.isCancelled) {
1493 d8426ffb Miltiadis Vasilakis
                    [pool drain];
1494 d8426ffb Miltiadis Vasilakis
                    return;
1495 d8426ffb Miltiadis Vasilakis
                }
1496 67e3336f Miltiadis Vasilakis
                NSString *destinationObjectName;
1497 67e3336f Miltiadis Vasilakis
                if (![destinationNode isEqualTo:node.parent]) {
1498 67e3336f Miltiadis Vasilakis
                    destinationObjectName = [objectNamePrefix stringByAppendingPathComponent:node.displayName];
1499 67e3336f Miltiadis Vasilakis
                    if (node.pithosObject.subdir)
1500 67e3336f Miltiadis Vasilakis
                        destinationObjectName = [destinationObjectName stringByAppendingString:@"/"];
1501 67e3336f Miltiadis Vasilakis
                } else {
1502 919cb043 Miltiadis Vasilakis
                    destinationObjectName = [PithosUtilities safeSubdirNameForPithos:pithos 
1503 919cb043 Miltiadis Vasilakis
                                                                       containerName:containerName 
1504 919cb043 Miltiadis Vasilakis
                                                                          subdirName:node.pithosObject.name];
1505 67e3336f Miltiadis Vasilakis
                }
1506 d8426ffb Miltiadis Vasilakis
                if (operation.isCancelled) {
1507 d8426ffb Miltiadis Vasilakis
                    [pool drain];
1508 d8426ffb Miltiadis Vasilakis
                    return;
1509 d8426ffb Miltiadis Vasilakis
                }
1510 919cb043 Miltiadis Vasilakis
                NSArray *objectRequests = [PithosUtilities copyObjectRequestsForSubdirWithPithos:pithos 
1511 919cb043 Miltiadis Vasilakis
                                                                                   containerName:node.pithosContainer.name 
1512 919cb043 Miltiadis Vasilakis
                                                                                      objectName:node.pithosObject.name 
1513 919cb043 Miltiadis Vasilakis
                                                                        destinationContainerName:containerName 
1514 919cb043 Miltiadis Vasilakis
                                                                           destinationObjectName:destinationObjectName 
1515 919cb043 Miltiadis Vasilakis
                                                                                   checkIfExists:YES 
1516 919cb043 Miltiadis Vasilakis
                                                                                  sharingAccount:node.sharingAccount];
1517 d8426ffb Miltiadis Vasilakis
                if (!operation.isCancelled && objectRequests) {
1518 d8426ffb Miltiadis Vasilakis
                    ASIPithosObjectRequest *previousObjectRequest = nil;
1519 67e3336f Miltiadis Vasilakis
                    for (ASIPithosObjectRequest *objectRequest in objectRequests) {
1520 d8426ffb Miltiadis Vasilakis
                        if (operation.isCancelled) {
1521 d8426ffb Miltiadis Vasilakis
                            [pool drain];
1522 d8426ffb Miltiadis Vasilakis
                            return;
1523 d8426ffb Miltiadis Vasilakis
                        }
1524 67e3336f Miltiadis Vasilakis
                        objectRequest.delegate = self;
1525 4c1c46fd Miltiadis Vasilakis
                        objectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
1526 4c1c46fd Miltiadis Vasilakis
                        objectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
1527 4c1c46fd Miltiadis Vasilakis
                        NSString *messagePrefix = [NSString stringWithFormat:@"Copying '%@/%@' to '%@/%@'", 
1528 4c1c46fd Miltiadis Vasilakis
                                                   [objectRequest.userInfo objectForKey:@"sourceContainerName"], 
1529 4c1c46fd Miltiadis Vasilakis
                                                   [objectRequest.userInfo objectForKey:@"sourceObjectName"], 
1530 4c1c46fd Miltiadis Vasilakis
                                                   [objectRequest.userInfo objectForKey:@"destinationContainerName"], 
1531 4c1c46fd Miltiadis Vasilakis
                                                   [objectRequest.userInfo objectForKey:@"destinationObjectName"]];
1532 1b1e6fa1 Miltiadis Vasilakis
                        PithosActivity *activity = [activityFacility startActivityWithType:PithosActivityCopy 
1533 4c1c46fd Miltiadis Vasilakis
                                                                                   message:messagePrefix];
1534 1b1e6fa1 Miltiadis Vasilakis
                        [(NSMutableDictionary *)(objectRequest.userInfo) addEntriesFromDictionary:
1535 1b1e6fa1 Miltiadis Vasilakis
                         [NSDictionary dictionaryWithObjectsAndKeys:
1536 1b1e6fa1 Miltiadis Vasilakis
                          [NSArray arrayWithObject:destinationNode], @"forceRefreshNodes", 
1537 1b1e6fa1 Miltiadis Vasilakis
                          activity, @"activity", 
1538 4c1c46fd Miltiadis Vasilakis
                          [messagePrefix stringByAppendingString:@" (stopped)"], @"stoppedActivityMessage", 
1539 4c1c46fd Miltiadis Vasilakis
                          [messagePrefix stringByAppendingString:@" (failed)"], @"failedActivityMessage", 
1540 4c1c46fd Miltiadis Vasilakis
                          [messagePrefix stringByAppendingString:@" (finished)"], @"finishedActivityMessage", 
1541 4c1c46fd Miltiadis Vasilakis
                          [NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority", 
1542 1b1e6fa1 Miltiadis Vasilakis
                          [NSNumber numberWithUnsignedInteger:10], @"retries", 
1543 4c1c46fd Miltiadis Vasilakis
                          NSStringFromSelector(@selector(copyFinished:)), @"didFinishSelector", 
1544 4c1c46fd Miltiadis Vasilakis
                          NSStringFromSelector(@selector(requestFailed:)), @"didFailSelector", 
1545 4c1c46fd Miltiadis Vasilakis
                          copyNetworkQueue, @"networkQueue", 
1546 d8426ffb Miltiadis Vasilakis
                          @"copy", @"operationType", 
1547 1b1e6fa1 Miltiadis Vasilakis
                          nil]];
1548 d8426ffb Miltiadis Vasilakis
                        if (previousObjectRequest)
1549 d8426ffb Miltiadis Vasilakis
                            [objectRequest addDependency:previousObjectRequest];
1550 d8426ffb Miltiadis Vasilakis
                        previousObjectRequest = objectRequest;
1551 4c1c46fd Miltiadis Vasilakis
                        [copyNetworkQueue addOperation:[PithosUtilities prepareRequest:objectRequest priority:NSOperationQueuePriorityHigh]];
1552 33bf3856 Miltiadis Vasilakis
                    }
1553 f2f50f78 Miltiadis Vasilakis
                }
1554 4c1c46fd Miltiadis Vasilakis
                [pool drain];
1555 d8426ffb Miltiadis Vasilakis
            }];
1556 d8426ffb Miltiadis Vasilakis
            [copyQueue addOperation:operation];
1557 f2f50f78 Miltiadis Vasilakis
        }
1558 f2f50f78 Miltiadis Vasilakis
    }
1559 67e3336f Miltiadis Vasilakis
    return YES;
1560 f2f50f78 Miltiadis Vasilakis
}
1561 f2f50f78 Miltiadis Vasilakis
1562 f2f50f78 Miltiadis Vasilakis
#pragma mark -
1563 f2f50f78 Miltiadis Vasilakis
#pragma mark ASIHTTPRequestDelegate
1564 f2f50f78 Miltiadis Vasilakis
1565 4c1c46fd Miltiadis Vasilakis
- (void)performRequestFinishedDelegateInBackground:(ASIPithosRequest *)request {
1566 d8426ffb Miltiadis Vasilakis
    NSOperationQueue *callbackQueue;
1567 d8426ffb Miltiadis Vasilakis
    NSString *operationType = [request.userInfo objectForKey:@"operationType"];
1568 d8426ffb Miltiadis Vasilakis
    if ([operationType isEqualToString:@"move"])
1569 d8426ffb Miltiadis Vasilakis
        callbackQueue = moveCallbackQueue;
1570 d8426ffb Miltiadis Vasilakis
    else if ([operationType isEqualToString:@"copy"])
1571 d8426ffb Miltiadis Vasilakis
        callbackQueue = copyCallbackQueue;
1572 d8426ffb Miltiadis Vasilakis
    else if ([operationType isEqualToString:@"delete"])
1573 d8426ffb Miltiadis Vasilakis
        callbackQueue = deleteCallbackQueue;
1574 d8426ffb Miltiadis Vasilakis
    else if ([operationType isEqualToString:@"upload"])
1575 d8426ffb Miltiadis Vasilakis
        callbackQueue = uploadCallbackQueue;
1576 d8426ffb Miltiadis Vasilakis
    else if ([operationType isEqualToString:@"download"])
1577 d8426ffb Miltiadis Vasilakis
        callbackQueue = downloadCallbackQueue;
1578 4c1c46fd Miltiadis Vasilakis
    else
1579 d8426ffb Miltiadis Vasilakis
        dispatch_async(dispatch_get_main_queue(), ^{
1580 d8426ffb Miltiadis Vasilakis
            [activityFacility endActivity:[request.userInfo objectForKey:@"activity"] 
1581 d8426ffb Miltiadis Vasilakis
                              withMessage:[request.userInfo objectForKey:@"stoppedActivityMessage"]];
1582 d8426ffb Miltiadis Vasilakis
        });
1583 d8426ffb Miltiadis Vasilakis
    // Add an operation to the callbackQueue with a completionBlock for the case of cancellation
1584 d8426ffb Miltiadis Vasilakis
    NSInvocationOperation *operation = [[[NSInvocationOperation alloc] initWithTarget:self 
1585 d8426ffb Miltiadis Vasilakis
                                                                             selector:NSSelectorFromString([request.userInfo objectForKey:@"didFinishSelector"]) 
1586 d8426ffb Miltiadis Vasilakis
                                                                               object:request] autorelease];
1587 d8426ffb Miltiadis Vasilakis
    operation.completionBlock = ^{
1588 d8426ffb Miltiadis Vasilakis
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1589 d8426ffb Miltiadis Vasilakis
        if ([[request.userInfo objectForKey:@"operation"] isCancelled]) {
1590 d8426ffb Miltiadis Vasilakis
            dispatch_async(dispatch_get_main_queue(), ^{
1591 d8426ffb Miltiadis Vasilakis
                [activityFacility endActivity:[request.userInfo objectForKey:@"activity"] 
1592 d8426ffb Miltiadis Vasilakis
                                  withMessage:[request.userInfo objectForKey:@"stoppedActivityMessage"]];
1593 d8426ffb Miltiadis Vasilakis
            });
1594 d8426ffb Miltiadis Vasilakis
        }
1595 d8426ffb Miltiadis Vasilakis
        [pool drain];
1596 d8426ffb Miltiadis Vasilakis
    };
1597 d8426ffb Miltiadis Vasilakis
    [(NSMutableDictionary *)request.userInfo setObject:operation forKey:@"operation"];
1598 d8426ffb Miltiadis Vasilakis
    [callbackQueue addOperation:operation];
1599 4c1c46fd Miltiadis Vasilakis
}
1600 4c1c46fd Miltiadis Vasilakis
1601 4c1c46fd Miltiadis Vasilakis
- (void)performRequestFailedDelegateInBackground:(ASIPithosRequest *)request {
1602 d8426ffb Miltiadis Vasilakis
    if (request.isCancelled) {
1603 d8426ffb Miltiadis Vasilakis
        // Request has been cancelled 
1604 d8426ffb Miltiadis Vasilakis
        // The callbackQueue might be suspended so we call directly the callback method, since it does minimal work anyway
1605 d8426ffb Miltiadis Vasilakis
        [self performSelector:NSSelectorFromString([request.userInfo objectForKey:@"didFailSelector"]) 
1606 d8426ffb Miltiadis Vasilakis
                   withObject:request];
1607 d8426ffb Miltiadis Vasilakis
    } else {
1608 d8426ffb Miltiadis Vasilakis
        NSOperationQueue *callbackQueue;
1609 d8426ffb Miltiadis Vasilakis
        NSString *operationType = [request.userInfo objectForKey:@"operationType"];
1610 d8426ffb Miltiadis Vasilakis
        if ([operationType isEqualToString:@"move"])
1611 d8426ffb Miltiadis Vasilakis
            callbackQueue = moveCallbackQueue;
1612 d8426ffb Miltiadis Vasilakis
        else if ([operationType isEqualToString:@"copy"])
1613 d8426ffb Miltiadis Vasilakis
            callbackQueue = copyCallbackQueue;
1614 d8426ffb Miltiadis Vasilakis
        else if ([operationType isEqualToString:@"delete"])
1615 d8426ffb Miltiadis Vasilakis
            callbackQueue = deleteCallbackQueue;
1616 d8426ffb Miltiadis Vasilakis
        else if ([operationType isEqualToString:@"upload"])
1617 d8426ffb Miltiadis Vasilakis
            callbackQueue = uploadCallbackQueue;
1618 d8426ffb Miltiadis Vasilakis
        else if ([operationType isEqualToString:@"download"])
1619 d8426ffb Miltiadis Vasilakis
            callbackQueue = downloadCallbackQueue;
1620 d8426ffb Miltiadis Vasilakis
        else
1621 d8426ffb Miltiadis Vasilakis
            dispatch_async(dispatch_get_main_queue(), ^{
1622 d8426ffb Miltiadis Vasilakis
                [activityFacility endActivity:[request.userInfo objectForKey:@"activity"] 
1623 d8426ffb Miltiadis Vasilakis
                                  withMessage:[request.userInfo objectForKey:@"stoppedActivityMessage"]];
1624 d8426ffb Miltiadis Vasilakis
            });
1625 d8426ffb Miltiadis Vasilakis
        // Add an operation to the callbackQueue with a completionBlock for the case of cancellation
1626 d8426ffb Miltiadis Vasilakis
        NSInvocationOperation *operation = [[[NSInvocationOperation alloc] initWithTarget:self 
1627 d8426ffb Miltiadis Vasilakis
                                                                                 selector:NSSelectorFromString([request.userInfo objectForKey:@"didFailSelector"]) 
1628 d8426ffb Miltiadis Vasilakis
                                                                                   object:request] autorelease];
1629 d8426ffb Miltiadis Vasilakis
        operation.completionBlock = ^{
1630 d8426ffb Miltiadis Vasilakis
            NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1631 d8426ffb Miltiadis Vasilakis
            if ([[request.userInfo objectForKey:@"operation"] isCancelled]) {
1632 d8426ffb Miltiadis Vasilakis
                dispatch_async(dispatch_get_main_queue(), ^{
1633 d8426ffb Miltiadis Vasilakis
                    [activityFacility endActivity:[request.userInfo objectForKey:@"activity"] 
1634 d8426ffb Miltiadis Vasilakis
                                      withMessage:[request.userInfo objectForKey:@"stoppedActivityMessage"]];
1635 d8426ffb Miltiadis Vasilakis
                });
1636 d8426ffb Miltiadis Vasilakis
            }
1637 d8426ffb Miltiadis Vasilakis
            [pool drain];
1638 d8426ffb Miltiadis Vasilakis
        };
1639 d8426ffb Miltiadis Vasilakis
        [(NSMutableDictionary *)request.userInfo setObject:operation forKey:@"operation"];
1640 d8426ffb Miltiadis Vasilakis
        [callbackQueue addOperation:operation];
1641 d8426ffb Miltiadis Vasilakis
    }
1642 4c1c46fd Miltiadis Vasilakis
}
1643 4c1c46fd Miltiadis Vasilakis
1644 4c1c46fd Miltiadis Vasilakis
- (void)requestFailed:(ASIPithosRequest *)request {
1645 4c1c46fd Miltiadis Vasilakis
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1646 d8426ffb Miltiadis Vasilakis
    NSOperation *operation = [request.userInfo objectForKey:@"operation"];
1647 4c1c46fd Miltiadis Vasilakis
    NSLog(@"Request failed: %@", request.url);
1648 d8426ffb Miltiadis Vasilakis
    if (operation.isCancelled) {
1649 d8426ffb Miltiadis Vasilakis
        [pool drain];
1650 d8426ffb Miltiadis Vasilakis
        return;        
1651 d8426ffb Miltiadis Vasilakis
    }
1652 d8426ffb Miltiadis Vasilakis
    if (request.isCancelled) {
1653 4c1c46fd Miltiadis Vasilakis
        dispatch_async(dispatch_get_main_queue(), ^{
1654 4c1c46fd Miltiadis Vasilakis
            [activityFacility endActivity:[request.userInfo objectForKey:@"activity"] 
1655 4c1c46fd Miltiadis Vasilakis
                              withMessage:[request.userInfo objectForKey:@"stoppedActivityMessage"]];
1656 4c1c46fd Miltiadis Vasilakis
        });
1657 4c1c46fd Miltiadis Vasilakis
        [pool drain];
1658 4c1c46fd Miltiadis Vasilakis
        return;
1659 4c1c46fd Miltiadis Vasilakis
    }
1660 4c1c46fd Miltiadis Vasilakis
    NSUInteger retries = [[request.userInfo objectForKey:@"retries"] unsignedIntegerValue];
1661 4c1c46fd Miltiadis Vasilakis
    if (retries > 0) {
1662 4c1c46fd Miltiadis Vasilakis
        ASIPithosRequest *newRequest = (ASIPithosRequest *)[[PithosUtilities copyRequest:request] autorelease];
1663 4c1c46fd Miltiadis Vasilakis
        [(NSMutableDictionary *)(newRequest.userInfo)setObject:[NSNumber numberWithUnsignedInteger:(--retries)] forKey:@"retries"];
1664 4c1c46fd Miltiadis Vasilakis
        [(NSMutableDictionary *)(newRequest.userInfo)setObject:[NSNumber numberWithBool:NO] forKey:@"unexpectedResponseStatus"];
1665 4c1c46fd Miltiadis Vasilakis
        [[newRequest.userInfo objectForKey:@"networkQueue"] addOperation:[PithosUtilities prepareRequest:newRequest priority:[[newRequest.userInfo objectForKey:@"priority"] integerValue]]];
1666 4c1c46fd Miltiadis Vasilakis
    } else {
1667 4c1c46fd Miltiadis Vasilakis
        dispatch_async(dispatch_get_main_queue(), ^{
1668 4c1c46fd Miltiadis Vasilakis
            [activityFacility endActivity:[request.userInfo objectForKey:@"activity"] 
1669 4c1c46fd Miltiadis Vasilakis
                              withMessage:[request.userInfo objectForKey:@"failedActivityMessage"]];
1670 4c1c46fd Miltiadis Vasilakis
            if ([[request.userInfo objectForKey:@"unexpectedResponseStatus"] boolValue])
1671 4c1c46fd Miltiadis Vasilakis
                [PithosUtilities unexpectedResponseStatusAlertWithRequest:request];
1672 4c1c46fd Miltiadis Vasilakis
            else
1673 4c1c46fd Miltiadis Vasilakis
                [PithosUtilities httpRequestErrorAlertWithRequest:request];
1674 4c1c46fd Miltiadis Vasilakis
        });
1675 4c1c46fd Miltiadis Vasilakis
    }
1676 4c1c46fd Miltiadis Vasilakis
    [pool drain];
1677 4c1c46fd Miltiadis Vasilakis
}
1678 4c1c46fd Miltiadis Vasilakis
1679 d7c03491 Miltiadis Vasilakis
- (void)downloadObjectFinished:(ASIPithosObjectRequest *)objectRequest {
1680 4c1c46fd Miltiadis Vasilakis
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1681 d8426ffb Miltiadis Vasilakis
    NSOperation *operation = [objectRequest.userInfo objectForKey:@"operation"];
1682 1b1e6fa1 Miltiadis Vasilakis
    NSLog(@"Download finished: %@", objectRequest.url);
1683 d8426ffb Miltiadis Vasilakis
    if (operation.isCancelled) {
1684 d8426ffb Miltiadis Vasilakis
        [self requestFailed:objectRequest];
1685 d8426ffb Miltiadis Vasilakis
    } else if (objectRequest.responseStatusCode == 200) {
1686 1b1e6fa1 Miltiadis Vasilakis
        NSString *filePath = [objectRequest.userInfo objectForKey:@"filePath"];
1687 1b1e6fa1 Miltiadis Vasilakis
        PithosActivity *activity = [objectRequest.userInfo objectForKey:@"activity"];
1688 1b1e6fa1 Miltiadis Vasilakis
        NSUInteger totalBytes = activity.totalBytes;
1689 1b1e6fa1 Miltiadis Vasilakis
        
1690 470e6f81 Miltiadis Vasilakis
        // XXX change contentLength to objectContentLength if it is fixed in the server
1691 9ab4b378 Miltiadis Vasilakis
        if (([objectRequest contentLength] == 0) && ![PithosUtilities isContentTypeDirectory:[objectRequest contentType]]) {
1692 4650cc63 Miltiadis Vasilakis
            NSLog(@"Downloaded  0 bytes");
1693 0224a49f Miltiadis Vasilakis
            NSFileManager *fileManager = [NSFileManager defaultManager];
1694 0224a49f Miltiadis Vasilakis
            if (![fileManager fileExistsAtPath:filePath]) {
1695 0224a49f Miltiadis Vasilakis
                if (![fileManager createFileAtPath:filePath contents:nil attributes:nil]) {
1696 4c1c46fd Miltiadis Vasilakis
                    dispatch_async(dispatch_get_main_queue(), ^{
1697 4c1c46fd Miltiadis Vasilakis
                        NSAlert *alert = [[[NSAlert alloc] init] autorelease];
1698 4c1c46fd Miltiadis Vasilakis
                        [alert setMessageText:@"Create File Error"];
1699 4c1c46fd Miltiadis Vasilakis
                        [alert setInformativeText:[NSString stringWithFormat:@"Cannot create zero length file at %@", filePath]];
1700 4c1c46fd Miltiadis Vasilakis
                        [alert addButtonWithTitle:@"OK"];
1701 4c1c46fd Miltiadis Vasilakis
                        [alert runModal];
1702 4c1c46fd Miltiadis Vasilakis
                    });
1703 4650cc63 Miltiadis Vasilakis
                }
1704 d7c03491 Miltiadis Vasilakis
            }
1705 d7c03491 Miltiadis Vasilakis
        }
1706 470e6f81 Miltiadis Vasilakis
        
1707 f059e0e6 Miltiadis Vasilakis
        NSUInteger currentBytes = [objectRequest objectContentLength];
1708 470e6f81 Miltiadis Vasilakis
        if (currentBytes == 0)
1709 470e6f81 Miltiadis Vasilakis
            currentBytes = totalBytes;
1710 4c1c46fd Miltiadis Vasilakis
        dispatch_async(dispatch_get_main_queue(), ^{
1711 4c1c46fd Miltiadis Vasilakis
            [activityFacility endActivity:activity 
1712 4c1c46fd Miltiadis Vasilakis
                              withMessage:[objectRequest.userInfo objectForKey:@"finishedActivityMessage"] 
1713 4c1c46fd Miltiadis Vasilakis
                               totalBytes:totalBytes 
1714 4c1c46fd Miltiadis Vasilakis
                             currentBytes:currentBytes];
1715 4c1c46fd Miltiadis Vasilakis
        });
1716 1b1e6fa1 Miltiadis Vasilakis
    } else {
1717 4c1c46fd Miltiadis Vasilakis
        [(NSMutableDictionary *)(objectRequest.userInfo)setObject:[NSNumber numberWithBool:YES] forKey:@"unexpectedResponseStatus"];
1718 4c1c46fd Miltiadis Vasilakis
        [self requestFailed:objectRequest];
1719 1b1e6fa1 Miltiadis Vasilakis
    }
1720 4c1c46fd Miltiadis Vasilakis
    [pool drain];
1721 d7c03491 Miltiadis Vasilakis
}
1722 d7c03491 Miltiadis Vasilakis
1723 2ff5d98f Miltiadis Vasilakis
- (void)uploadDirectoryObjectFinished:(ASIPithosObjectRequest *)objectRequest {
1724 4c1c46fd Miltiadis Vasilakis
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1725 d8426ffb Miltiadis Vasilakis
    NSOperation *operation = [objectRequest.userInfo objectForKey:@"operation"];
1726 212a7d57 Miltiadis Vasilakis
    NSLog(@"Upload directory object finished: %@", objectRequest.url);
1727 d8426ffb Miltiadis Vasilakis
    if (operation.isCancelled) {
1728 d8426ffb Miltiadis Vasilakis
        [self requestFailed:objectRequest];
1729 d8426ffb Miltiadis Vasilakis
    } else if (objectRequest.responseStatusCode == 201) {
1730 212a7d57 Miltiadis Vasilakis
        NSLog(@"Directory object created: %@", objectRequest.url);
1731 4c1c46fd Miltiadis Vasilakis
        dispatch_async(dispatch_get_main_queue(), ^{
1732 4c1c46fd Miltiadis Vasilakis
            [activityFacility endActivity:[objectRequest.userInfo objectForKey:@"activity"] 
1733 4c1c46fd Miltiadis Vasilakis
                              withMessage:[objectRequest.userInfo objectForKey:@"finishedActivityMessage"]];
1734 4c1c46fd Miltiadis Vasilakis
        });
1735 212a7d57 Miltiadis Vasilakis
        for (PithosNode *node in [objectRequest.userInfo objectForKey:@"forceRefreshNodes"]) {
1736 212a7d57 Miltiadis Vasilakis
            [node forceRefresh];
1737 212a7d57 Miltiadis Vasilakis
        }
1738 212a7d57 Miltiadis Vasilakis
        for (PithosNode *node in [objectRequest.userInfo objectForKey:@"refreshNodes"]) {
1739 212a7d57 Miltiadis Vasilakis
            [node refresh];
1740 212a7d57 Miltiadis Vasilakis
        }
1741 212a7d57 Miltiadis Vasilakis
        if ([[objectRequest.userInfo objectForKey:@"forceRefresh"] boolValue])
1742 212a7d57 Miltiadis Vasilakis
            [self forceRefresh:self];
1743 212a7d57 Miltiadis Vasilakis
        else if ([[objectRequest.userInfo objectForKey:@"refresh"] boolValue])
1744 212a7d57 Miltiadis Vasilakis
            [self refresh:self];
1745 2ff5d98f Miltiadis Vasilakis
    } else {
1746 4c1c46fd Miltiadis Vasilakis
        [(NSMutableDictionary *)(objectRequest.userInfo)setObject:[NSNumber numberWithBool:YES] forKey:@"unexpectedResponseStatus"];
1747 4c1c46fd Miltiadis Vasilakis
        [self requestFailed:objectRequest];
1748 212a7d57 Miltiadis Vasilakis
    }
1749 4c1c46fd Miltiadis Vasilakis
    [pool drain];
1750 2ff5d98f Miltiadis Vasilakis
}
1751 2ff5d98f Miltiadis Vasilakis
1752 d7c03491 Miltiadis Vasilakis
- (void)uploadObjectUsingHashMapFinished:(ASIPithosObjectRequest *)objectRequest {
1753 4c1c46fd Miltiadis Vasilakis
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1754 d8426ffb Miltiadis Vasilakis
    NSOperation *operation = [objectRequest.userInfo objectForKey:@"operation"];
1755 1b1e6fa1 Miltiadis Vasilakis
    NSLog(@"Upload using hashmap finished: %@", objectRequest.url);
1756 470e6f81 Miltiadis Vasilakis
    NSString *fileName = [objectRequest.userInfo objectForKey:@"fileName"];
1757 470e6f81 Miltiadis Vasilakis
    PithosActivity *activity = [objectRequest.userInfo objectForKey:@"activity"];
1758 470e6f81 Miltiadis Vasilakis
    NSUInteger totalBytes = activity.totalBytes;
1759 470e6f81 Miltiadis Vasilakis
    NSUInteger currentBytes = activity.currentBytes;
1760 d8426ffb Miltiadis Vasilakis
    if (operation.isCancelled) {
1761 d8426ffb Miltiadis Vasilakis
        [self requestFailed:objectRequest];
1762 d8426ffb Miltiadis Vasilakis
    } else if (objectRequest.responseStatusCode == 201) {
1763 1b1e6fa1 Miltiadis Vasilakis
        NSLog(@"Object created: %@", objectRequest.url);
1764 4c1c46fd Miltiadis Vasilakis
        dispatch_async(dispatch_get_main_queue(), ^{
1765 4c1c46fd Miltiadis Vasilakis
            [activityFacility endActivity:activity 
1766 4c1c46fd Miltiadis Vasilakis
                              withMessage:[objectRequest.userInfo objectForKey:@"finishedActivityMessage"] 
1767 4c1c46fd Miltiadis Vasilakis
                               totalBytes:totalBytes 
1768 4c1c46fd Miltiadis Vasilakis
                             currentBytes:totalBytes];
1769 4c1c46fd Miltiadis Vasilakis
        });
1770 1b1e6fa1 Miltiadis Vasilakis
        for (PithosNode *node in [objectRequest.userInfo objectForKey:@"forceRefreshNodes"]) {
1771 1b1e6fa1 Miltiadis Vasilakis
            [node forceRefresh];
1772 1b1e6fa1 Miltiadis Vasilakis
        }
1773 1b1e6fa1 Miltiadis Vasilakis
        for (PithosNode *node in [objectRequest.userInfo objectForKey:@"refreshNodes"]) {
1774 4ae10a2b Miltiadis Vasilakis
            [node refresh];
1775 1b1e6fa1 Miltiadis Vasilakis
        }
1776 1b1e6fa1 Miltiadis Vasilakis
        if ([[objectRequest.userInfo objectForKey:@"forceRefresh"] boolValue])
1777 1b1e6fa1 Miltiadis Vasilakis
            [self forceRefresh:self];
1778 1b1e6fa1 Miltiadis Vasilakis
        else if ([[objectRequest.userInfo objectForKey:@"refresh"] boolValue])
1779 1b1e6fa1 Miltiadis Vasilakis
            [self refresh:self];        
1780 f2f50f78 Miltiadis Vasilakis
    } else if (objectRequest.responseStatusCode == 409) {
1781 1b1e6fa1 Miltiadis Vasilakis
        NSUInteger iteration = [[objectRequest.userInfo objectForKey:@"iteration"] unsignedIntegerValue];
1782 cab8f227 Miltiadis Vasilakis
        if (iteration == 0) {
1783 1b1e6fa1 Miltiadis Vasilakis
            NSLog(@"Upload iteration limit reached: %@", objectRequest.url);
1784 4c1c46fd Miltiadis Vasilakis
            dispatch_async(dispatch_get_main_queue(), ^{
1785 4c1c46fd Miltiadis Vasilakis
                [activityFacility endActivity:activity 
1786 4c1c46fd Miltiadis Vasilakis
                                  withMessage:[objectRequest.userInfo objectForKey:@"failedActivityMessage"]]; 
1787 4c1c46fd Miltiadis Vasilakis
                NSAlert *alert = [[[NSAlert alloc] init] autorelease];
1788 4c1c46fd Miltiadis Vasilakis
                [alert setMessageText:@"Upload Timeout"];
1789 4c1c46fd Miltiadis Vasilakis
                [alert setInformativeText:[NSString stringWithFormat:@"Upload iteration limit reached for object with path '%@'", 
1790 4c1c46fd Miltiadis Vasilakis
                                           [objectRequest.userInfo objectForKey:@"objectName"]]];
1791 4c1c46fd Miltiadis Vasilakis
                [alert addButtonWithTitle:@"OK"];
1792 4c1c46fd Miltiadis Vasilakis
                [alert runModal];
1793 4c1c46fd Miltiadis Vasilakis
            });
1794 4c1c46fd Miltiadis Vasilakis
            [pool drain];
1795 f2f50f78 Miltiadis Vasilakis
            return;
1796 f2f50f78 Miltiadis Vasilakis
        }
1797 1b1e6fa1 Miltiadis Vasilakis
        NSLog(@"object is missing hashes: %@", objectRequest.url);
1798 1b1e6fa1 Miltiadis Vasilakis
        NSIndexSet *missingBlocks = [PithosUtilities missingBlocksForHashes:[objectRequest.userInfo objectForKey:@"hashes"]
1799 919cb043 Miltiadis Vasilakis
                                                          withMissingHashes:[objectRequest hashes]];
1800 470e6f81 Miltiadis Vasilakis
        NSUInteger blockSize = [[objectRequest.userInfo objectForKey:@"blockSize"] unsignedIntegerValue];
1801 470e6f81 Miltiadis Vasilakis
        if (totalBytes >= [missingBlocks count]*blockSize)
1802 470e6f81 Miltiadis Vasilakis
            currentBytes = totalBytes - [missingBlocks count]*blockSize;
1803 4c1c46fd Miltiadis Vasilakis
        dispatch_async(dispatch_get_main_queue(), ^{
1804 4c1c46fd Miltiadis Vasilakis
            [activityFacility updateActivity:activity 
1805 4c1c46fd Miltiadis Vasilakis
                                 withMessage:[NSString stringWithFormat:@"Uploading '%@' (%.0f%%)", fileName, (totalBytes ? (100*(currentBytes + 0.0)/(totalBytes + 0.0)) : 100)] 
1806 4c1c46fd Miltiadis Vasilakis
                                  totalBytes:totalBytes 
1807 4c1c46fd Miltiadis Vasilakis
                                currentBytes:currentBytes];
1808 4c1c46fd Miltiadis Vasilakis
        });
1809 cab8f227 Miltiadis Vasilakis
        NSUInteger missingBlockIndex = [missingBlocks firstIndex];
1810 919cb043 Miltiadis Vasilakis
        __block ASIPithosContainerRequest *newContainerRequest = [PithosUtilities updateContainerDataRequestWithPithos:pithos 
1811 919cb043 Miltiadis Vasilakis
                                                                                                         containerName:[objectRequest.userInfo objectForKey:@"containerName"] 
1812 919cb043 Miltiadis Vasilakis
                                                                                                             blockSize:blockSize 
1813 919cb043 Miltiadis Vasilakis
                                                                                                               forFile:[objectRequest.userInfo objectForKey:@"filePath"] 
1814 919cb043 Miltiadis Vasilakis
                                                                                                     missingBlockIndex:missingBlockIndex 
1815 919cb043 Miltiadis Vasilakis
                                                                                                        sharingAccount:[objectRequest.userInfo objectForKey:@"sharingAccount"]];
1816 3b22507d Miltiadis Vasilakis
        newContainerRequest.delegate = self;
1817 4c1c46fd Miltiadis Vasilakis
        newContainerRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
1818 4c1c46fd Miltiadis Vasilakis
        newContainerRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
1819 3b22507d Miltiadis Vasilakis
        newContainerRequest.userInfo = objectRequest.userInfo;
1820 1b1e6fa1 Miltiadis Vasilakis
        [(NSMutableDictionary *)(newContainerRequest.userInfo) setObject:[NSNumber numberWithUnsignedInteger:(--iteration)] forKey:@"iteration"];
1821 1b1e6fa1 Miltiadis Vasilakis
        [(NSMutableDictionary *)(newContainerRequest.userInfo) setObject:[NSNumber numberWithUnsignedInteger:10] forKey:@"retries"];
1822 3b22507d Miltiadis Vasilakis
        [(NSMutableDictionary *)(newContainerRequest.userInfo) setObject:missingBlocks forKey:@"missingBlocks"];
1823 3b22507d Miltiadis Vasilakis
        [(NSMutableDictionary *)(newContainerRequest.userInfo) setObject:[NSNumber numberWithUnsignedInteger:missingBlockIndex] forKey:@"missingBlockIndex"];
1824 4c1c46fd Miltiadis Vasilakis
        [(NSMutableDictionary *)(newContainerRequest.userInfo) setObject:NSStringFromSelector(@selector(uploadMissingBlockFinished:)) forKey:@"didFinishSelector"];
1825 1b1e6fa1 Miltiadis Vasilakis
        [newContainerRequest setBytesSentBlock:^(unsigned long long size, unsigned long long total){
1826 1b1e6fa1 Miltiadis Vasilakis
            [activityFacility updateActivity:activity 
1827 4c1c46fd Miltiadis Vasilakis
                                 withMessage:[NSString stringWithFormat:@"Uploading '%@' (%.0f%%)", fileName, (activity.totalBytes ? (100*(activity.currentBytes + size + 0.0)/(activity.totalBytes + 0.0)) : 100)] 
1828 1b1e6fa1 Miltiadis Vasilakis
                                  totalBytes:activity.totalBytes 
1829 1b1e6fa1 Miltiadis Vasilakis
                                currentBytes:(activity.currentBytes + size)];
1830 1b1e6fa1 Miltiadis Vasilakis
        }];
1831 4c1c46fd Miltiadis Vasilakis
        [uploadNetworkQueue addOperation:[PithosUtilities prepareRequest:newContainerRequest priority:[[newContainerRequest.userInfo objectForKey:@"priority"] integerValue]]];
1832 1b1e6fa1 Miltiadis Vasilakis
    } else {
1833 4c1c46fd Miltiadis Vasilakis
        [(NSMutableDictionary *)(objectRequest.userInfo)setObject:[NSNumber numberWithBool:YES] forKey:@"unexpectedResponseStatus"];
1834 4c1c46fd Miltiadis Vasilakis
        [self requestFailed:objectRequest];
1835 1b1e6fa1 Miltiadis Vasilakis
    }
1836 4c1c46fd Miltiadis Vasilakis
    [pool drain];
1837 f2f50f78 Miltiadis Vasilakis
}
1838 f2f50f78 Miltiadis Vasilakis
1839 3b22507d Miltiadis Vasilakis
- (void)uploadMissingBlockFinished:(ASIPithosContainerRequest *)containerRequest {
1840 4c1c46fd Miltiadis Vasilakis
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1841 d8426ffb Miltiadis Vasilakis
    NSOperation *operation = [containerRequest.userInfo objectForKey:@"operation"];
1842 1b1e6fa1 Miltiadis Vasilakis
    NSLog(@"Upload of missing block finished: %@", containerRequest.url);
1843 470e6f81 Miltiadis Vasilakis
    NSUInteger blockSize = [[containerRequest.userInfo objectForKey:@"blockSize"] unsignedIntegerValue];
1844 470e6f81 Miltiadis Vasilakis
    NSString *fileName = [containerRequest.userInfo objectForKey:@"fileName"];
1845 470e6f81 Miltiadis Vasilakis
    PithosActivity *activity = [containerRequest.userInfo objectForKey:@"activity"];
1846 d8426ffb Miltiadis Vasilakis
    if (operation.isCancelled) {
1847 d8426ffb Miltiadis Vasilakis
        [self requestFailed:containerRequest];
1848 d8426ffb Miltiadis Vasilakis
    } else if (containerRequest.responseStatusCode == 202) {
1849 3b22507d Miltiadis Vasilakis
        NSIndexSet *missingBlocks = [containerRequest.userInfo objectForKey:@"missingBlocks"];
1850 3b22507d Miltiadis Vasilakis
        NSUInteger missingBlockIndex = [[containerRequest.userInfo objectForKey:@"missingBlockIndex"] unsignedIntegerValue];
1851 cab8f227 Miltiadis Vasilakis
        missingBlockIndex = [missingBlocks indexGreaterThanIndex:missingBlockIndex];
1852 cab8f227 Miltiadis Vasilakis
        if (missingBlockIndex == NSNotFound) {
1853 3b22507d Miltiadis Vasilakis
            NSArray *hashes = [containerRequest.userInfo objectForKey:@"hashes"];
1854 919cb043 Miltiadis Vasilakis
            ASIPithosObjectRequest *newObjectRequest = [PithosUtilities writeObjectDataRequestWithPithos:pithos 
1855 919cb043 Miltiadis Vasilakis
                                                                                           containerName:[containerRequest.userInfo objectForKey:@"containerName"] 
1856 919cb043 Miltiadis Vasilakis
                                                                                              objectName:[containerRequest.userInfo objectForKey:@"objectName"] 
1857 919cb043 Miltiadis Vasilakis
                                                                                             contentType:[containerRequest.userInfo objectForKey:@"contentType"] 
1858 919cb043 Miltiadis Vasilakis
                                                                                               blockSize:blockSize 
1859 919cb043 Miltiadis Vasilakis
                                                                                               blockHash:[containerRequest.userInfo objectForKey:@"blockHash"]
1860 919cb043 Miltiadis Vasilakis
                                                                                                 forFile:[containerRequest.userInfo objectForKey:@"filePath"] 
1861 919cb043 Miltiadis Vasilakis
                                                                                           checkIfExists:NO 
1862 919cb043 Miltiadis Vasilakis
                                                                                                  hashes:&hashes 
1863 919cb043 Miltiadis Vasilakis
                                                                                          sharingAccount:[containerRequest.userInfo objectForKey:@"sharingAccount"]];
1864 cab8f227 Miltiadis Vasilakis
            newObjectRequest.delegate = self;
1865 4c1c46fd Miltiadis Vasilakis
            newObjectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
1866 4c1c46fd Miltiadis Vasilakis
            newObjectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
1867 3b22507d Miltiadis Vasilakis
            newObjectRequest.userInfo = containerRequest.userInfo;
1868 1b1e6fa1 Miltiadis Vasilakis
            [(NSMutableDictionary *)(newObjectRequest.userInfo) setObject:[NSNumber numberWithUnsignedInteger:10] forKey:@"retries"];
1869 cab8f227 Miltiadis Vasilakis
            [(NSMutableDictionary *)(newObjectRequest.userInfo) removeObjectForKey:@"missingBlocks"];
1870 cab8f227 Miltiadis Vasilakis
            [(NSMutableDictionary *)(newObjectRequest.userInfo) removeObjectForKey:@"missingBlockIndex"];
1871 4c1c46fd Miltiadis Vasilakis
            [(NSMutableDictionary *)(newObjectRequest.userInfo) setObject:NSStringFromSelector(@selector(uploadObjectUsingHashMapFinished:)) forKey:@"didFinishSelector"];
1872 4c1c46fd Miltiadis Vasilakis
            [uploadNetworkQueue addOperation:[PithosUtilities prepareRequest:newObjectRequest priority:[[newObjectRequest.userInfo objectForKey:@"priority"] integerValue]]];
1873 cab8f227 Miltiadis Vasilakis
        } else {
1874 919cb043 Miltiadis Vasilakis
            __block ASIPithosContainerRequest *newContainerRequest = [PithosUtilities updateContainerDataRequestWithPithos:pithos 
1875 919cb043 Miltiadis Vasilakis
                                                                                                             containerName:[containerRequest.userInfo objectForKey:@"containerName"]
1876 919cb043 Miltiadis Vasilakis
                                                                                                                 blockSize:[[containerRequest.userInfo objectForKey:@"blockSize"] unsignedIntegerValue]
1877 919cb043 Miltiadis Vasilakis
                                                                                                                   forFile:[containerRequest.userInfo objectForKey:@"filePath"] 
1878 919cb043 Miltiadis Vasilakis
                                                                                                         missingBlockIndex:missingBlockIndex 
1879 919cb043 Miltiadis Vasilakis
                                                                                                            sharingAccount:[containerRequest.userInfo objectForKey:@"sharingAccount"]];
1880 3b22507d Miltiadis Vasilakis
            newContainerRequest.delegate = self;
1881 4c1c46fd Miltiadis Vasilakis
            newContainerRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
1882 4c1c46fd Miltiadis Vasilakis
            newContainerRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
1883 3b22507d Miltiadis Vasilakis
            newContainerRequest.userInfo = containerRequest.userInfo;
1884 1b1e6fa1 Miltiadis Vasilakis
            [(NSMutableDictionary *)(newContainerRequest.userInfo) setObject:[NSNumber numberWithUnsignedInteger:10] forKey:@"retries"];
1885 3b22507d Miltiadis Vasilakis
            [(NSMutableDictionary *)(newContainerRequest.userInfo) setObject:[NSNumber numberWithUnsignedInteger:missingBlockIndex] forKey:@"missingBlockIndex"];
1886 1b1e6fa1 Miltiadis Vasilakis
            [newContainerRequest setBytesSentBlock:^(unsigned long long size, unsigned long long total){
1887 1b1e6fa1 Miltiadis Vasilakis
                [activityFacility updateActivity:activity 
1888 4c1c46fd Miltiadis Vasilakis
                                     withMessage:[NSString stringWithFormat:@"Uploading '%@' (%.0f%%)", fileName, (activity.totalBytes ? (100*(activity.currentBytes + size + 0.0)/(activity.totalBytes + 0.0)) : 100)] 
1889 1b1e6fa1 Miltiadis Vasilakis
                                      totalBytes:activity.totalBytes 
1890 1b1e6fa1 Miltiadis Vasilakis
                                    currentBytes:(activity.currentBytes + size)];
1891 1b1e6fa1 Miltiadis Vasilakis
            }];
1892 4c1c46fd Miltiadis Vasilakis
            [uploadNetworkQueue addOperation:[PithosUtilities prepareRequest:newContainerRequest priority:[[newContainerRequest.userInfo objectForKey:@"priority"] integerValue]]];
1893 cab8f227 Miltiadis Vasilakis
        }
1894 f2f50f78 Miltiadis Vasilakis
    } else {
1895 4c1c46fd Miltiadis Vasilakis
        [(NSMutableDictionary *)(containerRequest.userInfo)setObject:[NSNumber numberWithBool:YES] forKey:@"unexpectedResponseStatus"];
1896 4c1c46fd Miltiadis Vasilakis
        [self requestFailed:containerRequest];
1897 1b1e6fa1 Miltiadis Vasilakis
    }
1898 4c1c46fd Miltiadis Vasilakis
    [pool drain];
1899 f2f50f78 Miltiadis Vasilakis
}
1900 f2f50f78 Miltiadis Vasilakis
1901 d41b3577 Miltiadis Vasilakis
- (void)moveFinished:(ASIPithosObjectRequest *)objectRequest {
1902 4c1c46fd Miltiadis Vasilakis
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1903 d8426ffb Miltiadis Vasilakis
    NSOperation *operation = [objectRequest.userInfo objectForKey:@"operation"];
1904 1b1e6fa1 Miltiadis Vasilakis
    NSLog(@"Move object finished: %@", objectRequest.url);
1905 d8426ffb Miltiadis Vasilakis
    if (operation.isCancelled) {
1906 d8426ffb Miltiadis Vasilakis
        [self requestFailed:objectRequest];
1907 d8426ffb Miltiadis Vasilakis
    } else if (objectRequest.responseStatusCode == 201) {
1908 4c1c46fd Miltiadis Vasilakis
        dispatch_async(dispatch_get_main_queue(), ^{
1909 4c1c46fd Miltiadis Vasilakis
            [activityFacility endActivity:[objectRequest.userInfo objectForKey:@"activity"] 
1910 4c1c46fd Miltiadis Vasilakis
                              withMessage:[objectRequest.userInfo objectForKey:@"finishedActivityMessage"]];
1911 4c1c46fd Miltiadis Vasilakis
        });
1912 1b1e6fa1 Miltiadis Vasilakis
        for (PithosNode *node in [objectRequest.userInfo objectForKey:@"forceRefreshNodes"]) {
1913 1b1e6fa1 Miltiadis Vasilakis
            [node forceRefresh];
1914 1b1e6fa1 Miltiadis Vasilakis
        }
1915 1b1e6fa1 Miltiadis Vasilakis
        for (PithosNode *node in [objectRequest.userInfo objectForKey:@"refreshNodes"]) {
1916 4ae10a2b Miltiadis Vasilakis
            [node refresh];
1917 1b1e6fa1 Miltiadis Vasilakis
        }
1918 1b1e6fa1 Miltiadis Vasilakis
        if ([[objectRequest.userInfo objectForKey:@"forceRefresh"] boolValue])
1919 1b1e6fa1 Miltiadis Vasilakis
            [self forceRefresh:self];
1920 1b1e6fa1 Miltiadis Vasilakis
        else if ([[objectRequest.userInfo objectForKey:@"refresh"] boolValue])
1921 1b1e6fa1 Miltiadis Vasilakis
            [self refresh:self];
1922 d41b3577 Miltiadis Vasilakis
    } else {
1923 4c1c46fd Miltiadis Vasilakis
        [(NSMutableDictionary *)(objectRequest.userInfo)setObject:[NSNumber numberWithBool:YES] forKey:@"unexpectedResponseStatus"];
1924 4c1c46fd Miltiadis Vasilakis
        [self requestFailed:objectRequest];
1925 1b1e6fa1 Miltiadis Vasilakis
    }
1926 4c1c46fd Miltiadis Vasilakis
    [pool drain];
1927 d41b3577 Miltiadis Vasilakis
}
1928 d41b3577 Miltiadis Vasilakis
1929 d41b3577 Miltiadis Vasilakis
- (void)copyFinished:(ASIPithosObjectRequest *)objectRequest {
1930 4c1c46fd Miltiadis Vasilakis
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1931 d8426ffb Miltiadis Vasilakis
    NSOperation *operation = [objectRequest.userInfo objectForKey:@"operation"];
1932 1b1e6fa1 Miltiadis Vasilakis
    NSLog(@"Copy object finished: %@", objectRequest.url);
1933 d8426ffb Miltiadis Vasilakis
    if (operation.isCancelled) {
1934 d8426ffb Miltiadis Vasilakis
        [self requestFailed:objectRequest];
1935 d8426ffb Miltiadis Vasilakis
    } else if (objectRequest.responseStatusCode == 201) {
1936 4c1c46fd Miltiadis Vasilakis
        dispatch_async(dispatch_get_main_queue(), ^{
1937 4c1c46fd Miltiadis Vasilakis
            [activityFacility endActivity:[objectRequest.userInfo objectForKey:@"activity"] 
1938 4c1c46fd Miltiadis Vasilakis
                              withMessage:[objectRequest.userInfo objectForKey:@"finishedActivityMessage"]];
1939 4c1c46fd Miltiadis Vasilakis
        });
1940 1b1e6fa1 Miltiadis Vasilakis
        for (PithosNode *node in [objectRequest.userInfo objectForKey:@"forceRefreshNodes"]) {
1941 1b1e6fa1 Miltiadis Vasilakis
            [node forceRefresh];
1942 1b1e6fa1 Miltiadis Vasilakis
        }
1943 1b1e6fa1 Miltiadis Vasilakis
        for (PithosNode *node in [objectRequest.userInfo objectForKey:@"refreshNodes"]) {
1944 1b1e6fa1 Miltiadis Vasilakis
            [node refresh];
1945 1b1e6fa1 Miltiadis Vasilakis
        }
1946 1b1e6fa1 Miltiadis Vasilakis
        if ([[objectRequest.userInfo objectForKey:@"forceRefresh"] boolValue])
1947 1b1e6fa1 Miltiadis Vasilakis
            [self forceRefresh:self];
1948 1b1e6fa1 Miltiadis Vasilakis
        else if ([[objectRequest.userInfo objectForKey:@"refresh"] boolValue])
1949 1b1e6fa1 Miltiadis Vasilakis
            [self refresh:self];
1950 d41b3577 Miltiadis Vasilakis
    } else {
1951 4c1c46fd Miltiadis Vasilakis
        [(NSMutableDictionary *)(objectRequest.userInfo)setObject:[NSNumber numberWithBool:YES] forKey:@"unexpectedResponseStatus"];
1952 4c1c46fd Miltiadis Vasilakis
        [self requestFailed:objectRequest];
1953 1b1e6fa1 Miltiadis Vasilakis
    }
1954 4c1c46fd Miltiadis Vasilakis
    [pool drain];
1955 d41b3577 Miltiadis Vasilakis
}
1956 d41b3577 Miltiadis Vasilakis
1957 212a7d57 Miltiadis Vasilakis
- (void)deleteObjectFinished:(ASIPithosObjectRequest *)objectRequest {
1958 4c1c46fd Miltiadis Vasilakis
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1959 d8426ffb Miltiadis Vasilakis
    NSOperation *operation = [objectRequest.userInfo objectForKey:@"operation"];
1960 212a7d57 Miltiadis Vasilakis
    NSLog(@"Delete object finished: %@", objectRequest.url);
1961 d8426ffb Miltiadis Vasilakis
    if (operation.isCancelled) {
1962 d8426ffb Miltiadis Vasilakis
        [self requestFailed:objectRequest];
1963 d8426ffb Miltiadis Vasilakis
    } else if (objectRequest.responseStatusCode == 204) {
1964 4c1c46fd Miltiadis Vasilakis
        dispatch_async(dispatch_get_main_queue(), ^{
1965 4c1c46fd Miltiadis Vasilakis
            [activityFacility endActivity:[objectRequest.userInfo objectForKey:@"activity"] 
1966 4c1c46fd Miltiadis Vasilakis
                              withMessage:[objectRequest.userInfo objectForKey:@"finishedActivityMessage"]];
1967 4c1c46fd Miltiadis Vasilakis
        });
1968 212a7d57 Miltiadis Vasilakis
        for (PithosNode *node in [objectRequest.userInfo objectForKey:@"forceRefreshNodes"]) {
1969 212a7d57 Miltiadis Vasilakis
            [node forceRefresh];
1970 212a7d57 Miltiadis Vasilakis
        }
1971 212a7d57 Miltiadis Vasilakis
        for (PithosNode *node in [objectRequest.userInfo objectForKey:@"refreshNodes"]) {
1972 212a7d57 Miltiadis Vasilakis
            [node refresh];
1973 212a7d57 Miltiadis Vasilakis
        }
1974 212a7d57 Miltiadis Vasilakis
        if ([[objectRequest.userInfo objectForKey:@"forceRefresh"] boolValue])
1975 212a7d57 Miltiadis Vasilakis
            [self forceRefresh:self];
1976 212a7d57 Miltiadis Vasilakis
        else if ([[objectRequest.userInfo objectForKey:@"refresh"] boolValue])
1977 212a7d57 Miltiadis Vasilakis
            [self refresh:self];
1978 212a7d57 Miltiadis Vasilakis
    } else {
1979 4c1c46fd Miltiadis Vasilakis
        [(NSMutableDictionary *)(objectRequest.userInfo)setObject:[NSNumber numberWithBool:YES] forKey:@"unexpectedResponseStatus"];
1980 4c1c46fd Miltiadis Vasilakis
        [self requestFailed:objectRequest];
1981 212a7d57 Miltiadis Vasilakis
    }
1982 4c1c46fd Miltiadis Vasilakis
    [pool drain];
1983 212a7d57 Miltiadis Vasilakis
}
1984 212a7d57 Miltiadis Vasilakis
1985 e5fdf4d9 Miltiadis Vasilakis
#pragma mark -
1986 6dc7e931 Miltiadis Vasilakis
#pragma mark NSSplitViewDelegate
1987 e5fdf4d9 Miltiadis Vasilakis
1988 e5fdf4d9 Miltiadis Vasilakis
- (CGFloat)splitView:(NSSplitView *)splitView constrainMinCoordinate:(CGFloat)proposedMinimumPosition ofSubviewAt:(NSInteger)dividerIndex {
1989 3b5f0a19 Miltiadis Vasilakis
    if (splitView == verticalSplitView)
1990 3b5f0a19 Miltiadis Vasilakis
        return 120;
1991 3b5f0a19 Miltiadis Vasilakis
    else
1992 1b1e6fa1 Miltiadis Vasilakis
        return ([horizontalSplitView bounds].size.height - 108);
1993 e5fdf4d9 Miltiadis Vasilakis
}
1994 e5fdf4d9 Miltiadis Vasilakis
1995 e5fdf4d9 Miltiadis Vasilakis
- (CGFloat)splitView:(NSSplitView *)splitView constrainMaxCoordinate:(CGFloat)proposedMaximumPosition ofSubviewAt:(NSInteger)dividerIndex {
1996 3b5f0a19 Miltiadis Vasilakis
    if (splitView == verticalSplitView)
1997 3b5f0a19 Miltiadis Vasilakis
        return 220;
1998 3b5f0a19 Miltiadis Vasilakis
    else
1999 1b1e6fa1 Miltiadis Vasilakis
        return ([horizontalSplitView bounds].size.height - 108);
2000 e5fdf4d9 Miltiadis Vasilakis
}
2001 e5fdf4d9 Miltiadis Vasilakis
2002 133b1f2d Miltiadis Vasilakis
- (CGFloat)splitView:(NSSplitView *)splitView constrainSplitPosition:(CGFloat)proposedPosition ofSubviewAt:(NSInteger)dividerIndex {
2003 3b5f0a19 Miltiadis Vasilakis
    if (splitView == verticalSplitView) {
2004 3b5f0a19 Miltiadis Vasilakis
        if (proposedPosition < 120)
2005 3b5f0a19 Miltiadis Vasilakis
            return 120;
2006 3b5f0a19 Miltiadis Vasilakis
        else if (proposedPosition > 220)
2007 3b5f0a19 Miltiadis Vasilakis
            return 220;
2008 3b5f0a19 Miltiadis Vasilakis
        else
2009 3b5f0a19 Miltiadis Vasilakis
            return proposedPosition;
2010 3b5f0a19 Miltiadis Vasilakis
    } else {
2011 1b1e6fa1 Miltiadis Vasilakis
        return ([horizontalSplitView bounds].size.height - 108);
2012 3b5f0a19 Miltiadis Vasilakis
    }
2013 133b1f2d Miltiadis Vasilakis
}
2014 133b1f2d Miltiadis Vasilakis
2015 e5fdf4d9 Miltiadis Vasilakis
#pragma mark -
2016 20f54e18 Miltiadis Vasilakis
#pragma mark NSOutlineViewDataSource
2017 20f54e18 Miltiadis Vasilakis
2018 20f54e18 Miltiadis Vasilakis
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
2019 20f54e18 Miltiadis Vasilakis
    if (item == nil)
2020 20f54e18 Miltiadis Vasilakis
        return 2;
2021 20f54e18 Miltiadis Vasilakis
    if (item == containersNode)
2022 20f54e18 Miltiadis Vasilakis
        return containersNodeChildren.count;
2023 20f54e18 Miltiadis Vasilakis
    if (item == sharedNode)
2024 20f54e18 Miltiadis Vasilakis
        return 2;
2025 20f54e18 Miltiadis Vasilakis
    return 0;
2026 20f54e18 Miltiadis Vasilakis
}
2027 20f54e18 Miltiadis Vasilakis
2028 20f54e18 Miltiadis Vasilakis
- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item {
2029 20f54e18 Miltiadis Vasilakis
    if (item == nil)
2030 20f54e18 Miltiadis Vasilakis
        return (!index ? containersNode : sharedNode);
2031 20f54e18 Miltiadis Vasilakis
    if (item == sharedNode)
2032 20f54e18 Miltiadis Vasilakis
        return (!index ? mySharedNode : othersSharedNode);
2033 20f54e18 Miltiadis Vasilakis
    return [containersNodeChildren objectAtIndex:index];
2034 20f54e18 Miltiadis Vasilakis
}
2035 20f54e18 Miltiadis Vasilakis
2036 20f54e18 Miltiadis Vasilakis
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
2037 20f54e18 Miltiadis Vasilakis
    if ((item == containersNode) || (item == sharedNode))
2038 20f54e18 Miltiadis Vasilakis
        return YES;
2039 20f54e18 Miltiadis Vasilakis
    return NO;
2040 20f54e18 Miltiadis Vasilakis
}
2041 20f54e18 Miltiadis Vasilakis
2042 20f54e18 Miltiadis Vasilakis
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item {
2043 20f54e18 Miltiadis Vasilakis
    PithosNode *node = (PithosNode *)item;
2044 20f54e18 Miltiadis Vasilakis
    return node;    
2045 20f54e18 Miltiadis Vasilakis
}
2046 20f54e18 Miltiadis Vasilakis
2047 67e3336f Miltiadis Vasilakis
#pragma mark Drag and Drop destination
2048 67e3336f Miltiadis Vasilakis
2049 67e3336f Miltiadis Vasilakis
- (NSDragOperation)outlineView:(NSOutlineView *)anOutlineView 
2050 67e3336f Miltiadis Vasilakis
                  validateDrop:(id<NSDraggingInfo>)info 
2051 67e3336f Miltiadis Vasilakis
                  proposedItem:(id)item 
2052 67e3336f Miltiadis Vasilakis
            proposedChildIndex:(NSInteger)index {
2053 67e3336f Miltiadis Vasilakis
    NSDragOperation result = NSDragOperationNone;
2054 67e3336f Miltiadis Vasilakis
    if ((item == nil) || (index != NSOutlineViewDropOnItemIndex))
2055 67e3336f Miltiadis Vasilakis
        return result;
2056 67e3336f Miltiadis Vasilakis
    PithosNode *dropNode = (PithosNode *)item;
2057 67e3336f Miltiadis Vasilakis
    if ([dropNode class] != [PithosContainerNode class])
2058 67e3336f Miltiadis Vasilakis
        return result;
2059 67e3336f Miltiadis Vasilakis
    if ([[[info draggingPasteboard] types] containsObject:NSFilenamesPboardType]) {
2060 67e3336f Miltiadis Vasilakis
        result = NSDragOperationCopy;
2061 67e3336f Miltiadis Vasilakis
    } else if ([[[info draggingPasteboard] types] containsObject:NSFilesPromisePboardType]) {
2062 67e3336f Miltiadis Vasilakis
        if ([info draggingSourceOperationMask] & NSDragOperationMove) {
2063 67e3336f Miltiadis Vasilakis
            // NSDragOperationCopy | NSDragOperationMove -> NSDragOperationMove
2064 67e3336f Miltiadis Vasilakis
            if (![dropNode isEqualTo:draggedParentNode])
2065 67e3336f Miltiadis Vasilakis
                result = NSDragOperationMove;
2066 67e3336f Miltiadis Vasilakis
        } else if ([info draggingSourceOperationMask] & NSDragOperationCopy) {
2067 67e3336f Miltiadis Vasilakis
            // NSDragOperationCopy (Option modifier) -> NSDragOperationCopy
2068 67e3336f Miltiadis Vasilakis
            result = NSDragOperationCopy;
2069 67e3336f Miltiadis Vasilakis
        }
2070 67e3336f Miltiadis Vasilakis
    }
2071 67e3336f Miltiadis Vasilakis
   return result;
2072 67e3336f Miltiadis Vasilakis
}
2073 67e3336f Miltiadis Vasilakis
2074 67e3336f Miltiadis Vasilakis
- (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id<NSDraggingInfo>)info item:(id)item childIndex:(NSInteger)index {
2075 67e3336f Miltiadis Vasilakis
    if ([[[info draggingPasteboard] types] containsObject:NSFilenamesPboardType]) {
2076 67e3336f Miltiadis Vasilakis
        NSArray *filenames = [[info draggingPasteboard] propertyListForType:NSFilenamesPboardType];
2077 67e3336f Miltiadis Vasilakis
        NSLog(@"drag in operation: %lu filenames: %@", [info draggingSourceOperationMask], filenames);
2078 67e3336f Miltiadis Vasilakis
        if (item && (index == NSOutlineViewDropOnItemIndex) && (filenames != nil)) {
2079 67e3336f Miltiadis Vasilakis
            PithosNode *node = (PithosNode *)item;
2080 67e3336f Miltiadis Vasilakis
            NSLog(@"drag in node: %@", node.url);
2081 67e3336f Miltiadis Vasilakis
            return [self uploadFiles:filenames toNode:node];
2082 67e3336f Miltiadis Vasilakis
        }
2083 67e3336f Miltiadis Vasilakis
    } else if ([[[info draggingPasteboard] types] containsObject:NSFilesPromisePboardType]) {
2084 67e3336f Miltiadis Vasilakis
        NSLog(@"drag local operation: %lu nodes: %@", [info draggingSourceOperationMask], draggedNodes);
2085 67e3336f Miltiadis Vasilakis
        if (item && (index == NSOutlineViewDropOnItemIndex) && (draggedNodes != nil)) {
2086 67e3336f Miltiadis Vasilakis
            PithosNode *node = (PithosNode *)item;
2087 67e3336f Miltiadis Vasilakis
            NSLog(@"drag local node: %@", node.url);
2088 67e3336f Miltiadis Vasilakis
            if ([info draggingSourceOperationMask] & NSDragOperationMove)
2089 67e3336f Miltiadis Vasilakis
                return [self moveNodes:draggedNodes toNode:node];
2090 67e3336f Miltiadis Vasilakis
            else if ([info draggingSourceOperationMask] & NSDragOperationCopy)
2091 67e3336f Miltiadis Vasilakis
                return [self copyNodes:draggedNodes toNode:node];
2092 67e3336f Miltiadis Vasilakis
        }
2093 67e3336f Miltiadis Vasilakis
    }
2094 67e3336f Miltiadis Vasilakis
    return NO;
2095 67e3336f Miltiadis Vasilakis
}
2096 67e3336f Miltiadis Vasilakis
2097 20f54e18 Miltiadis Vasilakis
#pragma mark -
2098 e5fdf4d9 Miltiadis Vasilakis
#pragma mark NSOutlineViewDelegate
2099 e5fdf4d9 Miltiadis Vasilakis
2100 e5fdf4d9 Miltiadis Vasilakis
- (BOOL)outlineView:outlineView shouldSelectItem:(id)item {
2101 20f54e18 Miltiadis Vasilakis
    if ((item == containersNode) || (item == sharedNode))
2102 20f54e18 Miltiadis Vasilakis
        return NO;
2103 20f54e18 Miltiadis Vasilakis
    return YES;
2104 e5fdf4d9 Miltiadis Vasilakis
}
2105 e5fdf4d9 Miltiadis Vasilakis
2106 e5fdf4d9 Miltiadis Vasilakis
- (BOOL)outlineView:(NSOutlineView *)outlineView isGroupItem:(id)item {
2107 20f54e18 Miltiadis Vasilakis
    if ((item == containersNode) || (item == sharedNode))
2108 20f54e18 Miltiadis Vasilakis
        return YES;
2109 20f54e18 Miltiadis Vasilakis
    return NO;
2110 e5fdf4d9 Miltiadis Vasilakis
}
2111 e5fdf4d9 Miltiadis Vasilakis
2112 e5fdf4d9 Miltiadis Vasilakis
- (void)outlineViewSelectionDidChange:(NSNotification *)notification {
2113 20f54e18 Miltiadis Vasilakis
    PithosNode *node = (PithosNode *)[outlineView itemAtRow:[outlineView selectedRow]];
2114 e5fdf4d9 Miltiadis Vasilakis
    if (node) {
2115 e5fdf4d9 Miltiadis Vasilakis
        rootNode = node;
2116 e5fdf4d9 Miltiadis Vasilakis
        [browser loadColumnZero];
2117 20f54e18 Miltiadis Vasilakis
        [self refresh:nil];
2118 e5fdf4d9 Miltiadis Vasilakis
    }
2119 e5fdf4d9 Miltiadis Vasilakis
}
2120 e5fdf4d9 Miltiadis Vasilakis
2121 857217b0 Miltiadis Vasilakis
#pragma mark -
2122 857217b0 Miltiadis Vasilakis
#pragma mark NSMenuDelegate
2123 857217b0 Miltiadis Vasilakis
2124 857217b0 Miltiadis Vasilakis
- (void)menuNeedsUpdate:(NSMenu *)menu {
2125 857217b0 Miltiadis Vasilakis
    [menu removeAllItems];
2126 6a9b9f40 Miltiadis Vasilakis
    NSMenuItem *menuItem;
2127 c950a94d Miltiadis Vasilakis
    NSString *menuItemTitle;
2128 8f62f46a Miltiadis Vasilakis
    BOOL nodeContextMenu = NO;
2129 f059e0e6 Miltiadis Vasilakis
    PithosNode *menuNode = nil;
2130 8f62f46a Miltiadis Vasilakis
    NSMutableArray *menuNodes;
2131 8f62f46a Miltiadis Vasilakis
    if (menu == browserMenu) {
2132 8f62f46a Miltiadis Vasilakis
        NSInteger column = [browser clickedColumn];
2133 8f62f46a Miltiadis Vasilakis
        NSInteger row = [browser clickedRow];
2134 8f62f46a Miltiadis Vasilakis
        if ((column == -1) || (row == -1)) {
2135 8f62f46a Miltiadis Vasilakis
            // General context menu
2136 8f62f46a Miltiadis Vasilakis
            NSArray *menuNodesIndexPaths = [browser selectionIndexPaths];
2137 8f62f46a Miltiadis Vasilakis
            if ([menuNodesIndexPaths count] == 0) {
2138 8f62f46a Miltiadis Vasilakis
                menuNode = [browser parentForItemsInColumn:0];
2139 8f62f46a Miltiadis Vasilakis
            } else if (([menuNodesIndexPaths count] != 1) || 
2140 8f62f46a Miltiadis Vasilakis
                       ([[browser itemAtIndexPath:[menuNodesIndexPaths objectAtIndex:0]] class] == [PithosObjectNode class])) {
2141 8f62f46a Miltiadis Vasilakis
                menuNode = [browser parentForItemsInColumn:([[menuNodesIndexPaths objectAtIndex:0] length] - 1)];
2142 8f62f46a Miltiadis Vasilakis
            } else {
2143 8f62f46a Miltiadis Vasilakis
                menuNode = [browser itemAtIndexPath:[menuNodesIndexPaths objectAtIndex:0]];
2144 8f62f46a Miltiadis Vasilakis
            }
2145 1ca8da38 Miltiadis Vasilakis
        } else {
2146 8f62f46a Miltiadis Vasilakis
            // Node context menu
2147 8f62f46a Miltiadis Vasilakis
            NSIndexPath *clickedNodeIndexPath = [[browser indexPathForColumn:column] indexPathByAddingIndex:row];
2148 8f62f46a Miltiadis Vasilakis
            NSArray *menuNodesIndexPaths = [browser selectionIndexPaths];
2149 8f62f46a Miltiadis Vasilakis
            menuNodes = [NSMutableArray arrayWithCapacity:[menuNodesIndexPaths count]];
2150 8f62f46a Miltiadis Vasilakis
            if ([menuNodesIndexPaths containsObject:clickedNodeIndexPath]) {
2151 8f62f46a Miltiadis Vasilakis
                for (NSIndexPath *nodeIndexPath in menuNodesIndexPaths) {
2152 8f62f46a Miltiadis Vasilakis
                    [menuNodes addObject:[browser itemAtIndexPath:nodeIndexPath]];
2153 8f62f46a Miltiadis Vasilakis
                }
2154 8f62f46a Miltiadis Vasilakis
            } else {
2155 8f62f46a Miltiadis Vasilakis
                [menuNodes addObject:[browser itemAtIndexPath:clickedNodeIndexPath]];
2156 8f62f46a Miltiadis Vasilakis
            }
2157 8f62f46a Miltiadis Vasilakis
            nodeContextMenu = YES;
2158 1ca8da38 Miltiadis Vasilakis
        }
2159 8f62f46a Miltiadis Vasilakis
    } else if (menu == outlineViewMenu) {
2160 8f62f46a Miltiadis Vasilakis
        NSInteger row = [outlineView clickedRow];
2161 8f62f46a Miltiadis Vasilakis
        if (row == -1)
2162 8f62f46a Miltiadis Vasilakis
            row = [outlineView selectedRow];
2163 8f62f46a Miltiadis Vasilakis
        if (row == -1)
2164 8f62f46a Miltiadis Vasilakis
            return;
2165 8f62f46a Miltiadis Vasilakis
        menuNode = [outlineView itemAtRow:row];
2166 8f62f46a Miltiadis Vasilakis
    }
2167 8f62f46a Miltiadis Vasilakis
2168 8f62f46a Miltiadis Vasilakis
    if (!nodeContextMenu) {
2169 8f62f46a Miltiadis Vasilakis
        // General context menu
2170 8f62f46a Miltiadis Vasilakis
        if (([menuNode class] == [PithosAccountNode class]) || 
2171 8f62f46a Miltiadis Vasilakis
            ([menuNode class] == [PithosSharingAccountsNode class]) ||
2172 8f62f46a Miltiadis Vasilakis
            ([menuNode class] == [PithosEmptyNode class]))
2173 4ae10a2b Miltiadis Vasilakis
            return;
2174 4ae10a2b Miltiadis Vasilakis
        BOOL shared = menuNode.shared;
2175 af3b9f06 Miltiadis Vasilakis
        BOOL sharingAccount = (menuNode.sharingAccount != nil);
2176 8f62f46a Miltiadis Vasilakis
        // New Folder
2177 af3b9f06 Miltiadis Vasilakis
        if (!shared && !sharingAccount) {
2178 4ae10a2b Miltiadis Vasilakis
            menuItem = [[[NSMenuItem alloc] initWithTitle:@"New Folder" action:@selector(menuNewFolder:) keyEquivalent:@""] autorelease];
2179 4ae10a2b Miltiadis Vasilakis
            [menuItem setRepresentedObject:menuNode];
2180 4ae10a2b Miltiadis Vasilakis
            [menu addItem:menuItem];
2181 4ae10a2b Miltiadis Vasilakis
            [menu addItem:[NSMenuItem separatorItem]];
2182 4ae10a2b Miltiadis Vasilakis
        }
2183 515cd8db Miltiadis Vasilakis
        // Get Info
2184 c950a94d Miltiadis Vasilakis
        menuItem = [[[NSMenuItem alloc] initWithTitle:@"Get Info" action:@selector(menuGetInfo:) keyEquivalent:@""] autorelease];
2185 c950a94d Miltiadis Vasilakis
        [menuItem setRepresentedObject:[NSArray arrayWithObject:menuNode]];
2186 515cd8db Miltiadis Vasilakis
        [menu addItem:menuItem];
2187 8f62f46a Miltiadis Vasilakis
        // Paste
2188 af3b9f06 Miltiadis Vasilakis
        if (!shared && !sharingAccount) {
2189 4ae10a2b Miltiadis Vasilakis
            if (clipboardNodes) {
2190 4ae10a2b Miltiadis Vasilakis
                NSUInteger clipboardNodesCount = [clipboardNodes count];
2191 4ae10a2b Miltiadis Vasilakis
                if (clipboardNodesCount == 0) {
2192 4ae10a2b Miltiadis Vasilakis
                    self.clipboardNodes = nil;
2193 4ae10a2b Miltiadis Vasilakis
                } else if (clipboardCopy || ![menuNode isEqualTo:clipboardParentNode]) {
2194 4ae10a2b Miltiadis Vasilakis
                    if (clipboardNodesCount == 1)
2195 4ae10a2b Miltiadis Vasilakis
                        menuItemTitle = [NSString stringWithString:@"Paste Item"];
2196 4ae10a2b Miltiadis Vasilakis
                    else
2197 4ae10a2b Miltiadis Vasilakis
                        menuItemTitle = [NSString stringWithString:@"Paste Items"];
2198 4ae10a2b Miltiadis Vasilakis
                    [menu addItem:[NSMenuItem separatorItem]];
2199 4ae10a2b Miltiadis Vasilakis
                    menuItem = [[[NSMenuItem alloc] initWithTitle:menuItemTitle action:@selector(menuPaste:) keyEquivalent:@""] autorelease];
2200 4ae10a2b Miltiadis Vasilakis
                    [menuItem setRepresentedObject:menuNode];
2201 4ae10a2b Miltiadis Vasilakis
                    [menu addItem:menuItem];
2202 4ae10a2b Miltiadis Vasilakis
                }
2203 c950a94d Miltiadis Vasilakis
            }
2204 c950a94d Miltiadis Vasilakis
        }
2205 857217b0 Miltiadis Vasilakis
    } else {
2206 1ca8da38 Miltiadis Vasilakis
        // Node context menu
2207 c950a94d Miltiadis Vasilakis
        NSUInteger menuNodesCount = [menuNodes count];
2208 af3b9f06 Miltiadis Vasilakis
        PithosNode *firstMenuNode = (PithosNode *)[menuNodes objectAtIndex:0];
2209 af3b9f06 Miltiadis Vasilakis
        BOOL shared = firstMenuNode.shared;
2210 af3b9f06 Miltiadis Vasilakis
        BOOL sharingAccount = (firstMenuNode.sharingAccount != nil);
2211 8f62f46a Miltiadis Vasilakis
        // Move to Trash (pithos container only)
2212 8f62f46a Miltiadis Vasilakis
        // Delete
2213 af3b9f06 Miltiadis Vasilakis
        if (!shared && !sharingAccount) {
2214 4ae10a2b Miltiadis Vasilakis
            if ([rootNode class] == [PithosContainerNode class]) {
2215 4ae10a2b Miltiadis Vasilakis
                if ([rootNode.pithosContainer.name isEqualToString:@"pithos"]) {
2216 4ae10a2b Miltiadis Vasilakis
                    menuItem = [[[NSMenuItem alloc] initWithTitle:@"Move to Trash" action:@selector(menuMoveToTrash:) keyEquivalent:@""] autorelease];
2217 4ae10a2b Miltiadis Vasilakis
                    [menuItem setRepresentedObject:menuNodes];
2218 4ae10a2b Miltiadis Vasilakis
                    [menu addItem:menuItem];
2219 4ae10a2b Miltiadis Vasilakis
                }
2220 4ae10a2b Miltiadis Vasilakis
                menuItem = [[[NSMenuItem alloc] initWithTitle:@"Delete" action:@selector(menuDelete:) keyEquivalent:@""] autorelease];
2221 1ca8da38 Miltiadis Vasilakis
                [menuItem setRepresentedObject:menuNodes];
2222 6a9b9f40 Miltiadis Vasilakis
                [menu addItem:menuItem];
2223 4ae10a2b Miltiadis Vasilakis
                [menu addItem:[NSMenuItem separatorItem]];
2224 6a9b9f40 Miltiadis Vasilakis
            }
2225 6a9b9f40 Miltiadis Vasilakis
        }
2226 8f62f46a Miltiadis Vasilakis
        // Get Info
2227 af3b9f06 Miltiadis Vasilakis
        if (!sharingAccount || ([firstMenuNode class] != [PithosAccountNode class])) {
2228 af3b9f06 Miltiadis Vasilakis
            menuItem = [[[NSMenuItem alloc] initWithTitle:@"Get Info" action:@selector(menuGetInfo:) keyEquivalent:@""] autorelease];
2229 af3b9f06 Miltiadis Vasilakis
            [menuItem setRepresentedObject:menuNodes];
2230 af3b9f06 Miltiadis Vasilakis
            [menu addItem:menuItem];
2231 af3b9f06 Miltiadis Vasilakis
            
2232 af3b9f06 Miltiadis Vasilakis
            if ((!shared && !sharingAccount) || ([firstMenuNode class] != [PithosContainerNode class]))
2233 af3b9f06 Miltiadis Vasilakis
                [menu addItem:[NSMenuItem separatorItem]];
2234 af3b9f06 Miltiadis Vasilakis
        }
2235 8f62f46a Miltiadis Vasilakis
        // Cut
2236 af3b9f06 Miltiadis Vasilakis
        if (!shared && !sharingAccount) {
2237 4ae10a2b Miltiadis Vasilakis
            if (menuNodesCount == 1)
2238 4ae10a2b Miltiadis Vasilakis
                menuItemTitle = [NSString stringWithFormat:@"Cut \"%@\"", ((PithosNode *)[menuNodes objectAtIndex:0]).displayName];
2239 4ae10a2b Miltiadis Vasilakis
            else 
2240 4ae10a2b Miltiadis Vasilakis
                menuItemTitle = [NSString stringWithFormat:@"Cut %lu Items", menuNodesCount];
2241 4ae10a2b Miltiadis Vasilakis
            menuItem = [[[NSMenuItem alloc] initWithTitle:menuItemTitle action:@selector(menuCut:) keyEquivalent:@""] autorelease];
2242 4ae10a2b Miltiadis Vasilakis
            [menuItem setRepresentedObject:menuNodes];
2243 4ae10a2b Miltiadis Vasilakis
            [menu addItem:menuItem];
2244 20f54e18 Miltiadis Vasilakis
        }
2245 8f62f46a Miltiadis Vasilakis
        // Copy
2246 af3b9f06 Miltiadis Vasilakis
        if ((!shared && !sharingAccount) || 
2247 af3b9f06 Miltiadis Vasilakis
            (([firstMenuNode class] != [PithosContainerNode class]) && ([firstMenuNode class] != [PithosAccountNode class]))) {
2248 4ae10a2b Miltiadis Vasilakis
            if (menuNodesCount == 1)
2249 4ae10a2b Miltiadis Vasilakis
                menuItemTitle = [NSString stringWithFormat:@"Copy \"%@\"", ((PithosNode *)[menuNodes objectAtIndex:0]).displayName];
2250 4ae10a2b Miltiadis Vasilakis
            else 
2251 4ae10a2b Miltiadis Vasilakis
                menuItemTitle = [NSString stringWithFormat:@"Copy %lu Items", menuNodesCount];
2252 4ae10a2b Miltiadis Vasilakis
            menuItem = [[[NSMenuItem alloc] initWithTitle:menuItemTitle action:@selector(menuCopy:) keyEquivalent:@""] autorelease];
2253 4ae10a2b Miltiadis Vasilakis
            [menuItem setRepresentedObject:menuNodes];
2254 4ae10a2b Miltiadis Vasilakis
            [menu addItem:menuItem];
2255 20f54e18 Miltiadis Vasilakis
        }
2256 8f62f46a Miltiadis Vasilakis
        // Paste
2257 af3b9f06 Miltiadis Vasilakis
        if (!shared && !sharingAccount) {
2258 4ae10a2b Miltiadis Vasilakis
            if (menuNodesCount == 1) {
2259 4ae10a2b Miltiadis Vasilakis
                PithosNode *menuNode = [menuNodes objectAtIndex:0];
2260 4ae10a2b Miltiadis Vasilakis
                if (([menuNode class] == [PithosSubdirNode class]) && 
2261 4ae10a2b Miltiadis Vasilakis
                    (menuNode.pithosObject.subdir || ![menuNode.pithosObject.name hasSuffix:@"/"])) {
2262 4ae10a2b Miltiadis Vasilakis
                    if (clipboardNodes) {
2263 4ae10a2b Miltiadis Vasilakis
                        NSUInteger clipboardNodesCount = [clipboardNodes count];
2264 4ae10a2b Miltiadis Vasilakis
                        if (clipboardNodesCount == 0) {
2265 4ae10a2b Miltiadis Vasilakis
                            self.clipboardNodes = nil;
2266 4ae10a2b Miltiadis Vasilakis
                        } else if (clipboardCopy || ![menuNode isEqualTo:clipboardParentNode]) {
2267 4ae10a2b Miltiadis Vasilakis
                            if (clipboardNodesCount == 1)
2268 4ae10a2b Miltiadis Vasilakis
                                menuItemTitle = [NSString stringWithString:@"Paste Item"];
2269 4ae10a2b Miltiadis Vasilakis
                            else
2270 4ae10a2b Miltiadis Vasilakis
                                menuItemTitle = [NSString stringWithString:@"Paste Items"];
2271 4ae10a2b Miltiadis Vasilakis
                            menuItem = [[[NSMenuItem alloc] initWithTitle:menuItemTitle action:@selector(menuPaste:) keyEquivalent:@""] autorelease];
2272 4ae10a2b Miltiadis Vasilakis
                            [menuItem setRepresentedObject:menuNode];
2273 4ae10a2b Miltiadis Vasilakis
                            [menu addItem:menuItem];
2274 4ae10a2b Miltiadis Vasilakis
                        }
2275 c950a94d Miltiadis Vasilakis
                    }
2276 c950a94d Miltiadis Vasilakis
                }
2277 c950a94d Miltiadis Vasilakis
            }
2278 c950a94d Miltiadis Vasilakis
        }
2279 857217b0 Miltiadis Vasilakis
    }
2280 857217b0 Miltiadis Vasilakis
}
2281 857217b0 Miltiadis Vasilakis
2282 857217b0 Miltiadis Vasilakis
#pragma mark -
2283 857217b0 Miltiadis Vasilakis
#pragma mark Menu Actions
2284 857217b0 Miltiadis Vasilakis
2285 c950a94d Miltiadis Vasilakis
- (void)menuNewFolder:(NSMenuItem *)sender {
2286 c950a94d Miltiadis Vasilakis
    PithosNode *node = (PithosNode *)[sender representedObject];
2287 c950a94d Miltiadis Vasilakis
    if ([node class] == [PithosContainerNode class]) {
2288 d8426ffb Miltiadis Vasilakis
        // Operation: Create (upload) a new root application/directory object
2289 d8426ffb Miltiadis Vasilakis
        __block NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
2290 4c1c46fd Miltiadis Vasilakis
            NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
2291 d8426ffb Miltiadis Vasilakis
            if (operation.isCancelled) {
2292 d8426ffb Miltiadis Vasilakis
                [pool drain];
2293 d8426ffb Miltiadis Vasilakis
                return;
2294 d8426ffb Miltiadis Vasilakis
            }
2295 919cb043 Miltiadis Vasilakis
            NSString *safeObjectName = [PithosUtilities safeSubdirNameForPithos:pithos 
2296 919cb043 Miltiadis Vasilakis
                                                                  containerName:node.pithosContainer.name 
2297 919cb043 Miltiadis Vasilakis
                                                                     subdirName:@"untitled folder"];
2298 212a7d57 Miltiadis Vasilakis
            NSString *fileName = [safeObjectName lastPathComponent];
2299 d8426ffb Miltiadis Vasilakis
            if (operation.isCancelled) {
2300 d8426ffb Miltiadis Vasilakis
                [pool drain];
2301 d8426ffb Miltiadis Vasilakis
                return;
2302 d8426ffb Miltiadis Vasilakis
            }
2303 919cb043 Miltiadis Vasilakis
            ASIPithosObjectRequest *objectRequest = [ASIPithosObjectRequest writeObjectDataRequestWithPithos:pithos 
2304 919cb043 Miltiadis Vasilakis
                                                                                               containerName:node.pithosContainer.name 
2305 919cb043 Miltiadis Vasilakis
                                                                                                  objectName:safeObjectName 
2306 919cb043 Miltiadis Vasilakis
                                                                                                        eTag:nil 
2307 919cb043 Miltiadis Vasilakis
                                                                                                 contentType:@"application/directory" 
2308 919cb043 Miltiadis Vasilakis
                                                                                             contentEncoding:nil 
2309 919cb043 Miltiadis Vasilakis
                                                                                          contentDisposition:nil 
2310 919cb043 Miltiadis Vasilakis
                                                                                                    manifest:nil 
2311 919cb043 Miltiadis Vasilakis
                                                                                                     sharing:nil 
2312 919cb043 Miltiadis Vasilakis
                                                                                                    isPublic:ASIPithosObjectRequestPublicIgnore 
2313 919cb043 Miltiadis Vasilakis
                                                                                                    metadata:nil 
2314 919cb043 Miltiadis Vasilakis
                                                                                                        data:[NSData data]];
2315 c950a94d Miltiadis Vasilakis
            objectRequest.delegate = self;
2316 4c1c46fd Miltiadis Vasilakis
            objectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
2317 4c1c46fd Miltiadis Vasilakis
            objectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
2318 4c1c46fd Miltiadis Vasilakis
            NSString *messagePrefix = [NSString stringWithFormat:@"Creating directory '%@'", fileName];
2319 212a7d57 Miltiadis Vasilakis
            PithosActivity *activity = [activityFacility startActivityWithType:PithosActivityCreateDirectory 
2320 4c1c46fd Miltiadis Vasilakis
                                                                       message:messagePrefix];
2321 c950a94d Miltiadis Vasilakis
            objectRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
2322 212a7d57 Miltiadis Vasilakis
                                      fileName, @"fileName", 
2323 212a7d57 Miltiadis Vasilakis
                                      [NSArray arrayWithObject:node], @"refreshNodes", 
2324 212a7d57 Miltiadis Vasilakis
                                      [NSNumber numberWithBool:YES], @"refresh", 
2325 212a7d57 Miltiadis Vasilakis
                                      activity, @"activity", 
2326 4c1c46fd Miltiadis Vasilakis
                                      [messagePrefix stringByAppendingString:@" (stopped)"], @"stoppedActivityMessage", 
2327 4c1c46fd Miltiadis Vasilakis
                                      [messagePrefix stringByAppendingString:@" (failed)"], @"failedActivityMessage", 
2328 4c1c46fd Miltiadis Vasilakis
                                      [messagePrefix stringByAppendingString:@" (finished)"], @"finishedActivityMessage", 
2329 4c1c46fd Miltiadis Vasilakis
                                      [NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority", 
2330 212a7d57 Miltiadis Vasilakis
                                      [NSNumber numberWithUnsignedInteger:10], @"retries", 
2331 4c1c46fd Miltiadis Vasilakis
                                      NSStringFromSelector(@selector(uploadDirectoryObjectFinished:)), @"didFinishSelector", 
2332 4c1c46fd Miltiadis Vasilakis
                                      NSStringFromSelector(@selector(requestFailed:)), @"didFailSelector", 
2333 4c1c46fd Miltiadis Vasilakis
                                      uploadNetworkQueue, @"networkQueue", 
2334 d8426ffb Miltiadis Vasilakis
                                      @"upload", @"operationType", 
2335 c950a94d Miltiadis Vasilakis
                                      nil];
2336 4c1c46fd Miltiadis Vasilakis
            [uploadNetworkQueue addOperation:[PithosUtilities prepareRequest:objectRequest priority:NSOperationQueuePriorityHigh]];
2337 4c1c46fd Miltiadis Vasilakis
            [pool drain];
2338 d8426ffb Miltiadis Vasilakis
        }];
2339 d8426ffb Miltiadis Vasilakis
        [uploadQueue addOperation:operation];
2340 c950a94d Miltiadis Vasilakis
    } else if (([node class] == [PithosSubdirNode class]) && 
2341 212a7d57 Miltiadis Vasilakis
               (node.pithosObject.subdir || ![node.pithosObject.name hasSuffix:@"/"])) {
2342 d8426ffb Miltiadis Vasilakis
        // Operation: Create (upload) a new aplication/directory object
2343 d8426ffb Miltiadis Vasilakis
        __block NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
2344 4c1c46fd Miltiadis Vasilakis
            NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
2345 d8426ffb Miltiadis Vasilakis
            if (operation.isCancelled) {
2346 d8426ffb Miltiadis Vasilakis
                [pool drain];
2347 d8426ffb Miltiadis Vasilakis
                return;
2348 d8426ffb Miltiadis Vasilakis
            }
2349 919cb043 Miltiadis Vasilakis
            NSString *safeObjectName = [PithosUtilities safeSubdirNameForPithos:pithos 
2350 919cb043 Miltiadis Vasilakis
                                                                  containerName:node.pithosContainer.name 
2351 919cb043 Miltiadis Vasilakis
                                                                     subdirName:[node.pithosObject.name stringByAppendingPathComponent:@"untitled folder"]];
2352 212a7d57 Miltiadis Vasilakis
            NSString *fileName = [safeObjectName lastPathComponent];
2353 d8426ffb Miltiadis Vasilakis
            if (operation.isCancelled) {
2354 d8426ffb Miltiadis Vasilakis
                [pool drain];
2355 d8426ffb Miltiadis Vasilakis
                return;
2356 d8426ffb Miltiadis Vasilakis
            }
2357 919cb043 Miltiadis Vasilakis
            ASIPithosObjectRequest *objectRequest = [ASIPithosObjectRequest writeObjectDataRequestWithPithos:pithos 
2358 919cb043 Miltiadis Vasilakis
                                                                                               containerName:node.pithosContainer.name 
2359 919cb043 Miltiadis Vasilakis
                                                                                                  objectName:safeObjectName 
2360 919cb043 Miltiadis Vasilakis
                                                                                                        eTag:nil 
2361 919cb043 Miltiadis Vasilakis
                                                                                                 contentType:@"application/directory" 
2362 919cb043 Miltiadis Vasilakis
                                                                                             contentEncoding:nil 
2363 919cb043 Miltiadis Vasilakis
                                                                                          contentDisposition:nil 
2364 919cb043 Miltiadis Vasilakis
                                                                                                    manifest:nil 
2365 919cb043 Miltiadis Vasilakis
                                                                                                     sharing:nil 
2366 919cb043 Miltiadis Vasilakis
                                                                                                    isPublic:ASIPithosObjectRequestPublicIgnore 
2367 919cb043 Miltiadis Vasilakis
                                                                                                    metadata:nil 
2368 919cb043 Miltiadis Vasilakis
                                                                                                        data:[NSData data]];
2369 c950a94d Miltiadis Vasilakis
            objectRequest.delegate = self;
2370 4c1c46fd Miltiadis Vasilakis
            objectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
2371 4c1c46fd Miltiadis Vasilakis
            objectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
2372 4c1c46fd Miltiadis Vasilakis
            NSString *messagePrefix = [NSString stringWithFormat:@"Creating directory '%@'", fileName];
2373 212a7d57 Miltiadis Vasilakis
            PithosActivity *activity = [activityFacility startActivityWithType:PithosActivityCreateDirectory 
2374 4c1c46fd Miltiadis Vasilakis
                                                                       message:messagePrefix];
2375 c950a94d Miltiadis Vasilakis
            objectRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
2376 212a7d57 Miltiadis Vasilakis
                                      fileName, @"fileName", 
2377 212a7d57 Miltiadis Vasilakis
                                      [NSArray arrayWithObject:node], @"refreshNodes", 
2378 212a7d57 Miltiadis Vasilakis
                                      [NSNumber numberWithBool:YES], @"refresh", 
2379 212a7d57 Miltiadis Vasilakis
                                      activity, @"activity", 
2380 4c1c46fd Miltiadis Vasilakis
                                      [messagePrefix stringByAppendingString:@" (stopped)"], @"stoppedActivityMessage", 
2381 4c1c46fd Miltiadis Vasilakis
                                      [messagePrefix stringByAppendingString:@" (failed)"], @"failedActivityMessage", 
2382 4c1c46fd Miltiadis Vasilakis
                                      [messagePrefix stringByAppendingString:@" (finished)"], @"finishedActivityMessage", 
2383 4c1c46fd Miltiadis Vasilakis
                                      [NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority", 
2384 212a7d57 Miltiadis Vasilakis
                                      [NSNumber numberWithUnsignedInteger:10], @"retries", 
2385 4c1c46fd Miltiadis Vasilakis
                                      NSStringFromSelector(@selector(uploadDirectoryObjectFinished:)), @"didFinishSelector", 
2386 4c1c46fd Miltiadis Vasilakis
                                      NSStringFromSelector(@selector(requestFailed:)), @"didFailSelector", 
2387 4c1c46fd Miltiadis Vasilakis
                                      uploadNetworkQueue, @"networkQueue", 
2388 d8426ffb Miltiadis Vasilakis
                                      @"upload", @"operationType", 
2389 212a7d57 Miltiadis Vasilakis
                                      nil];
2390 4c1c46fd Miltiadis Vasilakis
            [uploadNetworkQueue addOperation:[PithosUtilities prepareRequest:objectRequest priority:NSOperationQueuePriorityHigh]];
2391 4c1c46fd Miltiadis Vasilakis
            [pool drain];
2392 d8426ffb Miltiadis Vasilakis
        }];
2393 d8426ffb Miltiadis Vasilakis
        [uploadQueue addOperation:operation];
2394 1ca8da38 Miltiadis Vasilakis
    }
2395 1ca8da38 Miltiadis Vasilakis
}
2396 1ca8da38 Miltiadis Vasilakis
2397 c950a94d Miltiadis Vasilakis
- (void)menuGetInfo:(NSMenuItem *)sender {
2398 1ca8da38 Miltiadis Vasilakis
    for (PithosNode *node in ((NSArray *)[sender representedObject])) {
2399 133b1f2d Miltiadis Vasilakis
        [node showPithosNodeInfo:sender];
2400 133b1f2d Miltiadis Vasilakis
    }
2401 857217b0 Miltiadis Vasilakis
}
2402 857217b0 Miltiadis Vasilakis
2403 c950a94d Miltiadis Vasilakis
- (void)menuDelete:(NSMenuItem *)sender {
2404 1ca8da38 Miltiadis Vasilakis
    for (PithosNode *node in ((NSArray *)[sender representedObject])) {
2405 133b1f2d Miltiadis Vasilakis
        if (([node class] == [PithosObjectNode class]) || 
2406 212a7d57 Miltiadis Vasilakis
            (([node class] == [PithosSubdirNode class]) && !node.pithosObject.subdir && [node.pithosObject.name hasSuffix:@"/"])) {
2407 d8426ffb Miltiadis Vasilakis
            // Operation: Delete an object or subdir/ node
2408 d8426ffb Miltiadis Vasilakis
            __block NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
2409 4c1c46fd Miltiadis Vasilakis
                NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
2410 d8426ffb Miltiadis Vasilakis
                if (operation.isCancelled) {
2411 d8426ffb Miltiadis Vasilakis
                    [pool drain];
2412 d8426ffb Miltiadis Vasilakis
                    return;
2413 d8426ffb Miltiadis Vasilakis
                }
2414 4c1c46fd Miltiadis Vasilakis
                NSString *fileName = [node.pithosObject.name lastPathComponent];
2415 4c1c46fd Miltiadis Vasilakis
                if ([node.pithosObject.name hasSuffix:@"/"])
2416 4c1c46fd Miltiadis Vasilakis
                    fileName = [fileName stringByAppendingString:@"/"];
2417 919cb043 Miltiadis Vasilakis
                ASIPithosObjectRequest *objectRequest = [ASIPithosObjectRequest deleteObjectRequestWithPithos:pithos 
2418 919cb043 Miltiadis Vasilakis
                                                                                                containerName:node.pithosContainer.name 
2419 919cb043 Miltiadis Vasilakis
                                                                                                   objectName:node.pithosObject.name];
2420 d8426ffb Miltiadis Vasilakis
                if (operation.isCancelled) {
2421 d8426ffb Miltiadis Vasilakis
                    [pool drain];
2422 d8426ffb Miltiadis Vasilakis
                    return;
2423 d8426ffb Miltiadis Vasilakis
                }
2424 4c1c46fd Miltiadis Vasilakis
                objectRequest.delegate = self;
2425 4c1c46fd Miltiadis Vasilakis
                objectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
2426 4c1c46fd Miltiadis Vasilakis
                objectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
2427 4c1c46fd Miltiadis Vasilakis
                NSString *messagePrefix = [NSString stringWithFormat:@"Deleting '%@'", fileName];
2428 4c1c46fd Miltiadis Vasilakis
                PithosActivity *activity = [activityFacility startActivityWithType:PithosActivityDelete 
2429 4c1c46fd Miltiadis Vasilakis
                                                                           message:messagePrefix];
2430 4c1c46fd Miltiadis Vasilakis
                objectRequest.userInfo = [NSMutableDictionary dictionaryWithObjectsAndKeys:
2431 4c1c46fd Miltiadis Vasilakis
                                          fileName, @"fileName", 
2432 4c1c46fd Miltiadis Vasilakis
                                          [NSArray arrayWithObject:node.parent], @"forceRefreshNodes", 
2433 4c1c46fd Miltiadis Vasilakis
                                          activity, @"activity", 
2434 4c1c46fd Miltiadis Vasilakis
                                          [messagePrefix stringByAppendingString:@" (stopped)"], @"stoppedActivityMessage", 
2435 4c1c46fd Miltiadis Vasilakis
                                          [messagePrefix stringByAppendingString:@" (failed)"], @"failedActivityMessage", 
2436 4c1c46fd Miltiadis Vasilakis
                                          [messagePrefix stringByAppendingString:@" (finished)"], @"finishedActivityMessage", 
2437 4c1c46fd Miltiadis Vasilakis
                                          [NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority", 
2438 4c1c46fd Miltiadis Vasilakis
                                          [NSNumber numberWithUnsignedInteger:10], @"retries", 
2439 4c1c46fd Miltiadis Vasilakis
                                          NSStringFromSelector(@selector(deleteObjectFinished:)), @"didFinishSelector", 
2440 4c1c46fd Miltiadis Vasilakis
                                          NSStringFromSelector(@selector(requestFailed:)), @"didFailSelector", 
2441 4c1c46fd Miltiadis Vasilakis
                                          deleteNetworkQueue, @"networkQueue", 
2442 d8426ffb Miltiadis Vasilakis
                                          @"delete", @"operationType", 
2443 4c1c46fd Miltiadis Vasilakis
                                          nil];
2444 4c1c46fd Miltiadis Vasilakis
                [deleteNetworkQueue addOperation:[PithosUtilities prepareRequest:objectRequest priority:NSOperationQueuePriorityHigh]];
2445 4c1c46fd Miltiadis Vasilakis
                [pool drain];
2446 d8426ffb Miltiadis Vasilakis
            }];
2447 d8426ffb Miltiadis Vasilakis
            [deleteQueue addOperation:operation];
2448 133b1f2d Miltiadis Vasilakis
        } else if ([node class] == [PithosSubdirNode class]) {
2449 d8426ffb Miltiadis Vasilakis
            // Operation: Delete a subdir node and its descendants
2450 d8426ffb Miltiadis Vasilakis
            // The resulting ASIPithosObjectRequests are chained through dependencies
2451 d8426ffb Miltiadis Vasilakis
            __block NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
2452 4c1c46fd Miltiadis Vasilakis
                NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
2453 d8426ffb Miltiadis Vasilakis
                if (operation.isCancelled) {
2454 d8426ffb Miltiadis Vasilakis
                    [pool drain];
2455 d8426ffb Miltiadis Vasilakis
                    return;
2456 d8426ffb Miltiadis Vasilakis
                }
2457 919cb043 Miltiadis Vasilakis
                NSArray *objectRequests = [PithosUtilities deleteObjectRequestsForSubdirWithPithos:pithos 
2458 919cb043 Miltiadis Vasilakis
                                                                                     containerName:node.pithosContainer.name 
2459 919cb043 Miltiadis Vasilakis
                                                                                        objectName:node.pithosObject.name];
2460 d8426ffb Miltiadis Vasilakis
                if (!operation.isCancelled && objectRequests) {
2461 d8426ffb Miltiadis Vasilakis
                    ASIPithosObjectRequest *previousObjectRequest = nil;
2462 1ca8da38 Miltiadis Vasilakis
                    for (ASIPithosObjectRequest *objectRequest in objectRequests) {
2463 d8426ffb Miltiadis Vasilakis
                        if (operation.isCancelled) {
2464 d8426ffb Miltiadis Vasilakis
                            [pool drain];
2465 d8426ffb Miltiadis Vasilakis
                            return;
2466 d8426ffb Miltiadis Vasilakis
                        }
2467 1ca8da38 Miltiadis Vasilakis
                        objectRequest.delegate = self;
2468 4c1c46fd Miltiadis Vasilakis
                        objectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
2469 4c1c46fd Miltiadis Vasilakis
                        objectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
2470 4c1c46fd Miltiadis Vasilakis
                        NSString *messagePrefix = [NSString stringWithFormat:@"Deleting '%@'", [objectRequest.userInfo objectForKey:@"fileName"]];
2471 212a7d57 Miltiadis Vasilakis
                        PithosActivity *activity = [activityFacility startActivityWithType:PithosActivityDelete 
2472 4c1c46fd Miltiadis Vasilakis
                                                                                   message:messagePrefix];
2473 212a7d57 Miltiadis Vasilakis
                        [(NSMutableDictionary *)(objectRequest.userInfo) addEntriesFromDictionary:
2474 212a7d57 Miltiadis Vasilakis
                         [NSDictionary dictionaryWithObjectsAndKeys:
2475 212a7d57 Miltiadis Vasilakis
                          [NSArray arrayWithObject:node.parent], @"forceRefreshNodes", 
2476 212a7d57 Miltiadis Vasilakis
                          activity, @"activity", 
2477 4c1c46fd Miltiadis Vasilakis
                          [messagePrefix stringByAppendingString:@" (stopped)"], @"stoppedActivityMessage", 
2478 4c1c46fd Miltiadis Vasilakis
                          [messagePrefix stringByAppendingString:@" (failed)"], @"failedActivityMessage", 
2479 4c1c46fd Miltiadis Vasilakis
                          [messagePrefix stringByAppendingString:@" (finished)"], @"finishedActivityMessage", 
2480 4c1c46fd Miltiadis Vasilakis
                          [NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority", 
2481 212a7d57 Miltiadis Vasilakis
                          [NSNumber numberWithUnsignedInteger:10], @"retries", 
2482 4c1c46fd Miltiadis Vasilakis
                          NSStringFromSelector(@selector(deleteObjectFinished:)), @"didFinishSelector", 
2483 4c1c46fd Miltiadis Vasilakis
                          NSStringFromSelector(@selector(requestFailed:)), @"didFailSelector", 
2484 4c1c46fd Miltiadis Vasilakis
                          deleteNetworkQueue, @"networkQueue", 
2485 d8426ffb Miltiadis Vasilakis
                          @"delete", @"operationType", 
2486 212a7d57 Miltiadis Vasilakis
                          nil]];
2487 d8426ffb Miltiadis Vasilakis
                        if (previousObjectRequest)
2488 d8426ffb Miltiadis Vasilakis
                            [objectRequest addDependency:previousObjectRequest];
2489 d8426ffb Miltiadis Vasilakis
                        previousObjectRequest = objectRequest;
2490 4c1c46fd Miltiadis Vasilakis
                        [deleteNetworkQueue addOperation:[PithosUtilities prepareRequest:objectRequest priority:NSOperationQueuePriorityHigh]];
2491 1ca8da38 Miltiadis Vasilakis
                    }
2492 6a9b9f40 Miltiadis Vasilakis
                }
2493 4c1c46fd Miltiadis Vasilakis
                [pool drain];
2494 d8426ffb Miltiadis Vasilakis
            }];
2495 d8426ffb Miltiadis Vasilakis
            [deleteQueue addOperation:operation];
2496 133b1f2d Miltiadis Vasilakis
        }
2497 133b1f2d Miltiadis Vasilakis
    }
2498 133b1f2d Miltiadis Vasilakis
}
2499 133b1f2d Miltiadis Vasilakis
2500 c950a94d Miltiadis Vasilakis
- (void)menuMoveToTrash:(NSMenuItem *)sender {
2501 1ca8da38 Miltiadis Vasilakis
    for (PithosNode *node in ((NSArray *)[sender representedObject])) {
2502 133b1f2d Miltiadis Vasilakis
        if (([node class] == [PithosObjectNode class]) || 
2503 133b1f2d Miltiadis Vasilakis
            (([node class] == [PithosSubdirNode class]) && 
2504 133b1f2d Miltiadis Vasilakis
             !node.pithosObject.subdir &&
2505 133b1f2d Miltiadis Vasilakis
             [node.pithosObject.name hasSuffix:@"/"])) {
2506 d8426ffb Miltiadis Vasilakis
            // Operation: Move to trash an object or subdir/ node
2507 d8426ffb Miltiadis Vasilakis
            __block NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
2508 4c1c46fd Miltiadis Vasilakis
                NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
2509 d8426ffb Miltiadis Vasilakis
                if (operation.isCancelled) {
2510 d8426ffb Miltiadis Vasilakis
                    [pool drain];
2511 d8426ffb Miltiadis Vasilakis
                    return;
2512 d8426ffb Miltiadis Vasilakis
                }
2513 919cb043 Miltiadis Vasilakis
                NSString *safeObjectName = [PithosUtilities safeObjectNameForPithos:pithos 
2514 919cb043 Miltiadis Vasilakis
                                                                      containerName:@"trash" 
2515 919cb043 Miltiadis Vasilakis
                                                                         objectName:node.pithosObject.name];
2516 d8426ffb Miltiadis Vasilakis
                if (!operation.isCancelled && safeObjectName) {
2517 919cb043 Miltiadis Vasilakis
                    ASIPithosObjectRequest *objectRequest = [PithosUtilities moveObjectRequestWithPithos:pithos 
2518 919cb043 Miltiadis Vasilakis
                                                                                           containerName:node.pithosContainer.name 
2519 919cb043 Miltiadis Vasilakis
                                                                                              objectName:node.pithosObject.name 
2520 919cb043 Miltiadis Vasilakis
                                                                                destinationContainerName:@"trash" 
2521 919cb043 Miltiadis Vasilakis
                                                                                   destinationObjectName:safeObjectName 
2522 919cb043 Miltiadis Vasilakis
                                                                                           checkIfExists:NO];
2523 d8426ffb Miltiadis Vasilakis
                    if (!operation.isCancelled && objectRequest) {
2524 d41b3577 Miltiadis Vasilakis
                        objectRequest.delegate = self;
2525 4c1c46fd Miltiadis Vasilakis
                        objectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
2526 4c1c46fd Miltiadis Vasilakis
                        objectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
2527 4c1c46fd Miltiadis Vasilakis
                        NSString *messagePrefix = [NSString stringWithFormat:@"Moving '%@/%@' to '%@/%@'", 
2528 4c1c46fd Miltiadis Vasilakis
                                                   [objectRequest.userInfo objectForKey:@"sourceContainerName"], 
2529 4c1c46fd Miltiadis Vasilakis
                                                   [objectRequest.userInfo objectForKey:@"sourceObjectName"], 
2530 4c1c46fd Miltiadis Vasilakis
                                                   [objectRequest.userInfo objectForKey:@"destinationContainerName"], 
2531 4c1c46fd Miltiadis Vasilakis
                                                   [objectRequest.userInfo objectForKey:@"destinationObjectName"]];
2532 212a7d57 Miltiadis Vasilakis
                        PithosActivity *activity = [activityFacility startActivityWithType:PithosActivityMove 
2533 4c1c46fd Miltiadis Vasilakis
                                                                                   message:messagePrefix];
2534 212a7d57 Miltiadis Vasilakis
                        [(NSMutableDictionary *)(objectRequest.userInfo) addEntriesFromDictionary:
2535 212a7d57 Miltiadis Vasilakis
                         [NSDictionary dictionaryWithObjectsAndKeys:
2536 212a7d57 Miltiadis Vasilakis
                          [NSArray arrayWithObject:node.parent], @"forceRefreshNodes", 
2537 212a7d57 Miltiadis Vasilakis
                          activity, @"activity", 
2538 4c1c46fd Miltiadis Vasilakis
                          [messagePrefix stringByAppendingString:@" (stopped)"], @"stoppedActivityMessage", 
2539 4c1c46fd Miltiadis Vasilakis
                          [messagePrefix stringByAppendingString:@" (failed)"], @"failedActivityMessage", 
2540 4c1c46fd Miltiadis Vasilakis
                          [messagePrefix stringByAppendingString:@" (finished)"], @"finishedActivityMessage", 
2541 4c1c46fd Miltiadis Vasilakis
                          [NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority", 
2542 212a7d57 Miltiadis Vasilakis
                          [NSNumber numberWithUnsignedInteger:10], @"retries", 
2543 4c1c46fd Miltiadis Vasilakis
                          NSStringFromSelector(@selector(moveFinished:)), @"didFinishSelector", 
2544 4c1c46fd Miltiadis Vasilakis
                          NSStringFromSelector(@selector(requestFailed:)), @"didFailSelector", 
2545 4c1c46fd Miltiadis Vasilakis
                          moveNetworkQueue, @"networkQueue", 
2546 d8426ffb Miltiadis Vasilakis
                          @"move", @"operationType", 
2547 212a7d57 Miltiadis Vasilakis
                          nil]];
2548 4c1c46fd Miltiadis Vasilakis
                        [moveNetworkQueue addOperation:[PithosUtilities prepareRequest:objectRequest priority:NSOperationQueuePriorityHigh]];
2549 d41b3577 Miltiadis Vasilakis
                    }
2550 1ca8da38 Miltiadis Vasilakis
                }
2551 4c1c46fd Miltiadis Vasilakis
                [pool drain];
2552 d8426ffb Miltiadis Vasilakis
            }];
2553 d8426ffb Miltiadis Vasilakis
            [moveQueue addOperation:operation];
2554 133b1f2d Miltiadis Vasilakis
        } else if ([node class] == [PithosSubdirNode class]) {
2555 d8426ffb Miltiadis Vasilakis
            // Operation: Move to trash a subdir node and its descendants
2556 d8426ffb Miltiadis Vasilakis
            // The resulting ASIPithosObjectRequests are chained through dependencies
2557 d8426ffb Miltiadis Vasilakis
            __block NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
2558 4c1c46fd Miltiadis Vasilakis
                NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
2559 d8426ffb Miltiadis Vasilakis
                if (operation.isCancelled) {
2560 d8426ffb Miltiadis Vasilakis
                    [pool drain];
2561 d8426ffb Miltiadis Vasilakis
                    return;
2562 d8426ffb Miltiadis Vasilakis
                }
2563 919cb043 Miltiadis Vasilakis
                NSString *safeObjectName = [PithosUtilities safeSubdirNameForPithos:pithos 
2564 919cb043 Miltiadis Vasilakis
                                                                      containerName:@"trash" 
2565 919cb043 Miltiadis Vasilakis
                                                                         subdirName:node.pithosObject.name];
2566 d8426ffb Miltiadis Vasilakis
                if (!operation.isCancelled && safeObjectName) {
2567 919cb043 Miltiadis Vasilakis
                    NSArray *objectRequests = [PithosUtilities moveObjectRequestsForSubdirWithPithos:pithos 
2568 919cb043 Miltiadis Vasilakis
                                                                                       containerName:node.pithosContainer.name 
2569 919cb043 Miltiadis Vasilakis
                                                                                          objectName:node.pithosObject.name 
2570 919cb043 Miltiadis Vasilakis
                                                                            destinationContainerName:@"trash" 
2571 919cb043 Miltiadis Vasilakis
                                                                               destinationObjectName:safeObjectName 
2572 919cb043 Miltiadis Vasilakis
                                                                                       checkIfExists:NO];
2573 d8426ffb Miltiadis Vasilakis
                    if (!operation.isCancelled && objectRequests) {
2574 d8426ffb Miltiadis Vasilakis
                        ASIPithosObjectRequest *previousObjectRequest = nil;
2575 1ca8da38 Miltiadis Vasilakis
                        for (ASIPithosObjectRequest *objectRequest in objectRequests) {
2576 d8426ffb Miltiadis Vasilakis
                            if (operation.isCancelled) {
2577 d8426ffb Miltiadis Vasilakis
                                [pool drain];
2578 d8426ffb Miltiadis Vasilakis
                                return;
2579 d8426ffb Miltiadis Vasilakis
                            }
2580 1ca8da38 Miltiadis Vasilakis
                            objectRequest.delegate = self;
2581 4c1c46fd Miltiadis Vasilakis
                            objectRequest.didFinishSelector = @selector(performRequestFinishedDelegateInBackground:);
2582 4c1c46fd Miltiadis Vasilakis
                            objectRequest.didFailSelector = @selector(performRequestFailedDelegateInBackground:);
2583 4c1c46fd Miltiadis Vasilakis
                            NSString *messagePrefix = [NSString stringWithFormat:@"Moving '%@/%@' to '%@/%@'", 
2584 4c1c46fd Miltiadis Vasilakis
                                                       [objectRequest.userInfo objectForKey:@"sourceContainerName"], 
2585 4c1c46fd Miltiadis Vasilakis
                                                       [objectRequest.userInfo objectForKey:@"sourceObjectName"], 
2586 4c1c46fd Miltiadis Vasilakis
                                                       [objectRequest.userInfo objectForKey:@"destinationContainerName"], 
2587 4c1c46fd Miltiadis Vasilakis
                                                       [objectRequest.userInfo objectForKey:@"destinationObjectName"]];
2588 212a7d57 Miltiadis Vasilakis
                            PithosActivity *activity = [activityFacility startActivityWithType:PithosActivityMove 
2589 4c1c46fd Miltiadis Vasilakis
                                                                                       message:messagePrefix];
2590 212a7d57 Miltiadis Vasilakis
                            [(NSMutableDictionary *)(objectRequest.userInfo) addEntriesFromDictionary:
2591 212a7d57 Miltiadis Vasilakis
                             [NSDictionary dictionaryWithObjectsAndKeys:
2592 212a7d57 Miltiadis Vasilakis
                              [NSArray arrayWithObject:node.parent], @"forceRefreshNodes", 
2593 212a7d57 Miltiadis Vasilakis
                              activity, @"activity", 
2594 4c1c46fd Miltiadis Vasilakis
                              [messagePrefix stringByAppendingString:@" (stopped)"], @"stoppedActivityMessage", 
2595 4c1c46fd Miltiadis Vasilakis
                              [messagePrefix stringByAppendingString:@" (failed)"], @"failedActivityMessage", 
2596 4c1c46fd Miltiadis Vasilakis
                              [messagePrefix stringByAppendingString:@" (finished)"], @"finishedActivityMessage", 
2597 4c1c46fd Miltiadis Vasilakis
                              [NSNumber numberWithInteger:NSOperationQueuePriorityHigh], @"priority", 
2598 212a7d57 Miltiadis Vasilakis
                              [NSNumber numberWithUnsignedInteger:10], @"retries", 
2599 4c1c46fd Miltiadis Vasilakis
                              NSStringFromSelector(@selector(moveFinished:)), @"didFinishSelector", 
2600 4c1c46fd Miltiadis Vasilakis
                              NSStringFromSelector(@selector(requestFailed:)), @"didFailSelector", 
2601 4c1c46fd Miltiadis Vasilakis
                              moveNetworkQueue, @"networkQueue", 
2602 d8426ffb Miltiadis Vasilakis
                              @"move", @"operationType", 
2603 212a7d57 Miltiadis Vasilakis
                              nil]];
2604 d8426ffb Miltiadis Vasilakis
                            if (previousObjectRequest)
2605 d8426ffb Miltiadis Vasilakis
                                [objectRequest addDependency:previousObjectRequest];
2606 d8426ffb Miltiadis Vasilakis
                            previousObjectRequest = objectRequest;
2607 4c1c46fd Miltiadis Vasilakis
                            [moveNetworkQueue addOperation:[PithosUtilities prepareRequest:objectRequest priority:NSOperationQueuePriorityHigh]];
2608 1ca8da38 Miltiadis Vasilakis
                        }
2609 133b1f2d Miltiadis Vasilakis
                    }
2610 133b1f2d Miltiadis Vasilakis
                }
2611 4c1c46fd Miltiadis Vasilakis
                [pool drain];
2612 d8426ffb Miltiadis Vasilakis
            }];
2613 d8426ffb Miltiadis Vasilakis
            [moveQueue addOperation:operation];
2614 133b1f2d Miltiadis Vasilakis
        }
2615 6a9b9f40 Miltiadis Vasilakis
    }
2616 6a9b9f40 Miltiadis Vasilakis
}
2617 6a9b9f40 Miltiadis Vasilakis
2618 c950a94d Miltiadis Vasilakis
- (void)menuCut:(NSMenuItem *)sender {
2619 c950a94d Miltiadis Vasilakis
    self.clipboardNodes = (NSArray *)[sender representedObject];
2620 c950a94d Miltiadis Vasilakis
    self.clipboardParentNode = ((PithosNode *)[clipboardNodes objectAtIndex:0]).parent;
2621 c950a94d Miltiadis Vasilakis
    self.clipboardCopy = NO;
2622 c950a94d Miltiadis Vasilakis
}
2623 c950a94d Miltiadis Vasilakis
2624 c950a94d Miltiadis Vasilakis
- (void)menuCopy:(NSMenuItem *)sender {
2625 c950a94d Miltiadis Vasilakis
    self.clipboardNodes = (NSArray *)[sender representedObject];
2626 c950a94d Miltiadis Vasilakis
    self.clipboardParentNode = ((PithosNode *)[clipboardNodes objectAtIndex:0]).parent;
2627 c950a94d Miltiadis Vasilakis
    self.clipboardCopy = YES;
2628 c950a94d Miltiadis Vasilakis
}
2629 c950a94d Miltiadis Vasilakis
2630 c950a94d Miltiadis Vasilakis
- (void)menuPaste:(NSMenuItem *)sender {
2631 c950a94d Miltiadis Vasilakis
    if (!clipboardNodes || ![clipboardNodes count])
2632 c950a94d Miltiadis Vasilakis
        return;
2633 c950a94d Miltiadis Vasilakis
    PithosNode *dropNode = (PithosNode *)[sender representedObject];
2634 c950a94d Miltiadis Vasilakis
    NSArray *localClipboardNodes = [NSArray arrayWithArray:clipboardNodes];
2635 c950a94d Miltiadis Vasilakis
    if (!clipboardCopy && ![dropNode isEqualTo:clipboardParentNode]) {
2636 c950a94d Miltiadis Vasilakis
        self.clipboardNodes = nil;
2637 c950a94d Miltiadis Vasilakis
        self.clipboardParentNode = nil;
2638 1b1e6fa1 Miltiadis Vasilakis
        [self moveNodes:localClipboardNodes toNode:dropNode];
2639 c950a94d Miltiadis Vasilakis
    } else {
2640 1b1e6fa1 Miltiadis Vasilakis
        [self copyNodes:localClipboardNodes toNode:dropNode];
2641 c950a94d Miltiadis Vasilakis
    }
2642 c950a94d Miltiadis Vasilakis
}
2643 c950a94d Miltiadis Vasilakis
    
2644 6a9b9f40 Miltiadis Vasilakis
#pragma mark -
2645 470e6f81 Miltiadis Vasilakis
#pragma mark PithosActivityFacilityDelegate
2646 470e6f81 Miltiadis Vasilakis
2647 470e6f81 Miltiadis Vasilakis
- (void)activityUpdate:(NSDictionary *)info {
2648 470e6f81 Miltiadis Vasilakis
    NSString *message = [info objectForKey:@"message"];
2649 470e6f81 Miltiadis Vasilakis
    NSUInteger runningActivitiesCount = [[info objectForKey:@"runningActivitiesCount"] unsignedIntegerValue];
2650 470e6f81 Miltiadis Vasilakis
//    NSUInteger endingActivitiesCount = [[info objectForKey:@"endingActivitiesCount"] unsignedIntegerValue];
2651 470e6f81 Miltiadis Vasilakis
    NSUInteger totalUploadBytes = [[info objectForKey:@"totalUploadBytes"] unsignedIntegerValue];
2652 470e6f81 Miltiadis Vasilakis
    NSUInteger currentUploadBytes = [[info objectForKey:@"currentUploadBytes"] unsignedIntegerValue];
2653 470e6f81 Miltiadis Vasilakis
    NSUInteger totalDownloadBytes = [[info objectForKey:@"totalDownloadBytes"] unsignedIntegerValue];
2654 470e6f81 Miltiadis Vasilakis
    NSUInteger currentDownloadBytes = [[info objectForKey:@"currentDownloadBytes"] unsignedIntegerValue];
2655 470e6f81 Miltiadis Vasilakis
    NSUInteger totalBytes = totalUploadBytes + totalDownloadBytes;
2656 470e6f81 Miltiadis Vasilakis
    if (runningActivitiesCount && totalBytes) {
2657 470e6f81 Miltiadis Vasilakis
        [activityProgressIndicator setDoubleValue:((currentUploadBytes + currentDownloadBytes + 0.0)/(totalBytes + 0.0))];
2658 470e6f81 Miltiadis Vasilakis
        [activityProgressIndicator startAnimation:self];
2659 470e6f81 Miltiadis Vasilakis
    } else {
2660 470e6f81 Miltiadis Vasilakis
        [activityProgressIndicator setDoubleValue:1.0];
2661 470e6f81 Miltiadis Vasilakis
        [activityProgressIndicator stopAnimation:self];
2662 470e6f81 Miltiadis Vasilakis
    }
2663 470e6f81 Miltiadis Vasilakis
    
2664 470e6f81 Miltiadis Vasilakis
    if (!message)
2665 2943d6d4 Miltiadis Vasilakis
        message = [[[[UsingSizeTransformer alloc] init] autorelease] transformedValue:accountNode.pithosAccount];
2666 470e6f81 Miltiadis Vasilakis
    [activityTextField setStringValue:message];
2667 470e6f81 Miltiadis Vasilakis
}
2668 6a9b9f40 Miltiadis Vasilakis
2669 e5fdf4d9 Miltiadis Vasilakis
@end