Revision 60731366

b/Classes/AccountDetailsViewController.h
6 6
//  The OpenStack project is provided under the Apache 2.0 license.
7 7
//
8 8

  
9
@class Provider, RootViewController, OpenStackAccount, ActivityIndicatorView;
9
@class Provider, RootViewController, OpenStackAccount;
10 10

  
11 11
@interface AccountDetailsViewController : UITableViewController <UITextFieldDelegate> {
12 12
    Provider *provider;
......
28 28

  
29 29
@property (nonatomic, retain) Provider *provider;
30 30
@property (nonatomic, retain) RootViewController *rootViewController;
31
@property (nonatomic, retain) ActivityIndicatorView *activityIndicatorView;
32 31

  
33 32
@property (nonatomic, retain) NSString *username;
34 33
@property (nonatomic, retain) NSString *authToken;
b/Classes/AccountDetailsViewController.m
26 26

  
27 27
@implementation AccountDetailsViewController
28 28

  
29
@synthesize provider, rootViewController, activityIndicatorView;
29
@synthesize provider, rootViewController;
30 30
@synthesize username, authToken;
31 31

  
32 32
#pragma mark - View lifecycle
......
73 73
- (void)dealloc {
74 74
    [provider release];
75 75
    [rootViewController release];
76
    [activityIndicatorView release];
77 76
    [username release];
78 77
    [authToken release];
79 78
    [super dealloc];
......
226 225
    [self authenticate];
227 226
}
228 227

  
229
#pragma mark - HTTP Response Handlers
230

  
231
- (void)authenticationSucceded:(OpenStackRequest *)request {
232
    [self.activityIndicatorView removeFromSuperview];
233
    if ([request isSuccess]) {
234
        NSString *storageURLString = [[request responseHeaders] objectForKey:@"X-Storage-Url"];
235
        if (storageURLString) {
236
            account.filesURL = [NSURL URLWithString:storageURLString];
237
        } else {
238
            account.filesURL = [[account.hostURL URLByAppendingPathComponent:@"v1"] URLByAppendingPathComponent:account.username];
239
        }
240
        [account persist];
241
        [rootViewController.tableView reloadData];
242
        [self.navigationController dismissModalViewControllerAnimated:YES];
243
    } else {
244
        self.navigationItem.rightBarButtonItem.enabled = YES;
245
        [self alert:@"Authentication Failure" message:@"Please check your Username and Token."];
246
    }
247
}
248

  
249
- (void)authenticationFailed:(OpenStackRequest *)request {
250
    [self.activityIndicatorView removeFromSuperview];
251
    self.navigationItem.rightBarButtonItem.enabled = YES;
252
    if ([request responseStatusCode] == 401) {
253
        [self alert:@"Authentication Failure" message:@"Please check your Username and Token."];
254
    } else {
255
        [self failOnBadConnection];
256
    }
257
}
228
#pragma mark - Authentication
258 229

  
259 230
- (void)authenticate {
260 231
    if (customProvider && (!providerNameTextField.text || [providerNameTextField.text isEqualToString:@""])) {
......
286 257
        account.authToken = authTokenTextField.text;
287 258
        account.hostURL = [account.provider.authEndpointURL URLByDeletingLastPathComponent];
288 259

  
289
        self.activityIndicatorView = [[[ActivityIndicatorView alloc] initWithText:@"Authenticating..."] autorelease];
290
        [self.activityIndicatorView addToView:self.view];
291
        
260
        __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Authenticating..."
261
                                                                                                       andAddToView:self.view];
292 262
        OpenStackRequest *request = [OpenStackRequest authenticationRequest:account];
293
        request.delegate = self;
294
        request.didFinishSelector = @selector(authenticationSucceded:);
295
        request.didFailSelector = @selector(authenticationFailed:);
263
        request.completionBlock = ^{
264
            [activityIndicatorView removeFromSuperview];
265
            if ([request isSuccess]) {
266
                NSString *storageURLString = [[request responseHeaders] objectForKey:@"X-Storage-Url"];
267
                if (storageURLString) {
268
                    account.filesURL = [NSURL URLWithString:storageURLString];
269
                } else {
270
                    account.filesURL = [[account.hostURL URLByAppendingPathComponent:@"v1"] URLByAppendingPathComponent:account.username];
271
                }
272
                [account persist];
273
                [rootViewController.tableView reloadData];
274
                [self.navigationController dismissModalViewControllerAnimated:YES];
275
            } else {
276
                self.navigationItem.rightBarButtonItem.enabled = YES;
277
                [self alert:@"Authentication Failure" message:@"Please check your Username and Token."];
278
            }
279
        };
280
        request.failedBlock = ^{
281
            [activityIndicatorView removeFromSuperview];
282
            self.navigationItem.rightBarButtonItem.enabled = YES;
283
            if ([request responseStatusCode] == 401) {
284
                [self alert:@"Authentication Failure" message:@"Please check your Username and Token."];
285
            } else {
286
                [self failOnBadConnection];
287
            }
288
        };
296 289
        [request startAsynchronous];
297 290
    }
298 291
}
b/Classes/AccountGroupsViewController.h
35 35
// interpreted as representing official policies, either expressed
36 36
// or implied, of GRNET S.A.
37 37

  
38
@class OpenStackAccount, ActivityIndicatorView;
38
@class OpenStackAccount;
39 39

  
40 40
@interface AccountGroupsViewController : UITableViewController {
41 41
    OpenStackAccount *account;
42 42
    NSMutableDictionary *groups;
43 43
    NSMutableDictionary *metadata;
44
    ActivityIndicatorView *activityIndicatorView;    
45 44
}
46 45

  
47 46
@property (nonatomic, retain) OpenStackAccount *account;
b/Classes/AccountGroupsViewController.m
60 60
    self.navigationItem.title = @"Groups";
61 61
    groups = [[NSMutableDictionary alloc] init];
62 62
    metadata = [[NSMutableDictionary alloc] init];
63
    
64
    NSString *activityMessage = @"Loading..";
65
    activityIndicatorView = [[ActivityIndicatorView alloc] initWithText:activityMessage];
66
    [activityIndicatorView addToView:self.view];
67
    
63

  
64
    __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Loading..."
65
                                                                                                   andAddToView:self.view];
68 66
    [[self.account.manager getStorageAccountInfo]
69 67
     success:^(OpenStackRequest *request) {
70 68
         [activityIndicatorView removeFromSuperview];
......
98 96
    [account release];
99 97
    [groups release];
100 98
    [metadata release];
101
    [activityIndicatorView release];
102 99
    [super dealloc];
103 100
}
104 101

  
b/Classes/AccountSettingsViewController.h
6 6
//  The OpenStack project is provided under the Apache 2.0 license.
7 7
//
8 8

  
9
@class OpenStackAccount, ActivityIndicatorView;
9
@class OpenStackAccount;
10 10

  
11 11
@interface AccountSettingsViewController : UITableViewController <UITextFieldDelegate> {
12 12
    UITextField *usernameTextField;
......
17 17
    
18 18
    NSString *username;
19 19
    NSString *authToken;
20
    
21
    ActivityIndicatorView *activityIndicatorView;
22 20
}
23 21

  
24 22
@property (nonatomic, retain) OpenStackAccount *account;
25 23

  
26 24
@property (nonatomic, retain) NSString *username;
27 25
@property (nonatomic, retain) NSString *authToken;
28
@property (nonatomic, retain) ActivityIndicatorView *activityIndicatorView;
29 26

  
30 27
- (void)saveButtonPressed:(id)sender;
31 28

  
b/Classes/AccountSettingsViewController.m
21 21

  
22 22
@implementation AccountSettingsViewController
23 23

  
24
@synthesize account, username, authToken, activityIndicatorView;
24
@synthesize account, username, authToken;
25 25

  
26 26
#pragma mark - View lifecycle
27 27

  
......
43 43
- (void)dealloc {
44 44
    [username release];
45 45
    [authToken release];
46
    [activityIndicatorView release];
47 46
    [account release];
48 47
    [super dealloc];
49 48
}
......
187 186
    [self authenticate];
188 187
}
189 188

  
190
#pragma mark - HTTP Response Handlers
191

  
192
- (void)authenticationSucceded:(OpenStackRequest *)request {
193
    [self.activityIndicatorView removeFromSuperview];
194
    if ([request isSuccess]) {
195
        account.username = request.account.username;
196
        account.authToken = request.account.authToken;
197
        NSString *storageURLString = [[request responseHeaders] objectForKey:@"X-Storage-Url"];
198
        if (storageURLString) {
199
            account.filesURL = [NSURL URLWithString:storageURLString];
200
        } else {
201
            account.filesURL = [[account.hostURL URLByAppendingPathComponent:@"v1"] URLByAppendingPathComponent:account.username];
202
        }
203
        [account persist];
204
    } else {
205
        self.navigationItem.rightBarButtonItem.enabled = YES;
206
        [self alert:@"Authentication Failure" message:@"Please check your Username and Token."];
207
    }
208
}
209

  
210
- (void)authenticationFailed:(OpenStackRequest *)request {
211
    [self.activityIndicatorView removeFromSuperview];
212
    self.navigationItem.rightBarButtonItem.enabled = YES;
213
    if ([request responseStatusCode] == 401) {
214
        [self alert:@"Authentication Failure" message:@"Please check your Username and Token."];
215
    } else {
216
        [self failOnBadConnection];
217
    }
218
}
189
#pragma mark - Authentication
219 190

  
220 191
- (void)authenticate {
221 192
    if (!usernameTextField.text || [usernameTextField.text isEqualToString:@""]) {
......
232 203
        temporaryAccount.username = usernameTextField.text;
233 204
        temporaryAccount.authToken = authTokenTextField.text;
234 205
        
235
        self.activityIndicatorView = [[[ActivityIndicatorView alloc] initWithText:@"Authenticating..."] autorelease];
236
        [self.activityIndicatorView addToView:self.view];
237
        
206
        __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Authenticating..."
207
                                                                                                       andAddToView:self.view];
238 208
        OpenStackRequest *request = [OpenStackRequest authenticationRequest:temporaryAccount];
239
        request.delegate = self;
240
        request.didFinishSelector = @selector(authenticationSucceded:);
241
        request.didFailSelector = @selector(authenticationFailed:);
209
        request.completionBlock = ^{
210
            [activityIndicatorView removeFromSuperview];
211
            if ([request isSuccess]) {
212
                account.username = request.account.username;
213
                account.authToken = request.account.authToken;
214
                NSString *storageURLString = [[request responseHeaders] objectForKey:@"X-Storage-Url"];
215
                if (storageURLString) {
216
                    account.filesURL = [NSURL URLWithString:storageURLString];
217
                } else {
218
                    account.filesURL = [[account.hostURL URLByAppendingPathComponent:@"v1"] URLByAppendingPathComponent:account.username];
219
                }
220
                [account persist];
221
            } else {
222
                self.navigationItem.rightBarButtonItem.enabled = YES;
223
                [self alert:@"Authentication Failure" message:@"Please check your Username and Token."];
224
            }
225
        };
226
        request.failedBlock = ^{
227
            [activityIndicatorView removeFromSuperview];
228
            self.navigationItem.rightBarButtonItem.enabled = YES;
229
            if ([request responseStatusCode] == 401) {
230
                [self alert:@"Authentication Failure" message:@"Please check your Username and Token."];
231
            } else {
232
                [self failOnBadConnection];
233
            }
234
        };
242 235
        [request startAsynchronous];
243 236
    }
244 237
}
b/Classes/ActivityIndicatorView.h
19 19
- (id)initWithText:(NSString *)text withProgress:(BOOL)withProgress;
20 20
- (id)initWithText:(NSString *)text;
21 21

  
22
+ (id)activityIndicatorViewWithText:(NSString *)text withProgress:(BOOL)withProgress;
23
+ (id)activityIndicatorViewWithText:(NSString *)text;
24

  
25
+ (id)activityIndicatorViewWithText:(NSString *)text withProgress:(BOOL)withProgress andAddToView:(UIView *)view scrollOffset:(CGFloat)offset;
26
+ (id)activityIndicatorViewWithText:(NSString *)text withProgress:(BOOL)withProgress andAddToView:(UIView *)view;
27
+ (id)activityIndicatorViewWithText:(NSString *)text andAddToView:(UIView *)view scrollOffset:(CGFloat)offset;
28
+ (id)activityIndicatorViewWithText:(NSString *)text andAddToView:(UIView *)view;
29

  
22 30
- (void)addToView:(UIView *)view scrollOffset:(CGFloat)offset;
23 31
- (void)addToView:(UIView *)view;
24 32
- (void)removeFromSuperview;
25
- (void)removeFromSuperviewAndRelease;
26 33

  
27 34
@end
b/Classes/ActivityIndicatorView.m
67 67
    return [self initWithText:text withProgress:NO];
68 68
}
69 69

  
70
+ (id)activityIndicatorViewWithText:(NSString *)text withProgress:(BOOL)withProgress {
71
    return [[[self alloc] initWithText:text withProgress:withProgress] autorelease];
72
}
73

  
74
+ (id)activityIndicatorViewWithText:(NSString *)text {
75
        return [self activityIndicatorViewWithText:text withProgress:NO];
76
}
77

  
78
+ (id)activityIndicatorViewWithText:(NSString *)text withProgress:(BOOL)withProgress andAddToView:(UIView *)view scrollOffset:(CGFloat)offset {
79
    ActivityIndicatorView *activityIndicatorView = [self activityIndicatorViewWithText:text withProgress:withProgress];
80
    [activityIndicatorView addToView:view scrollOffset:offset];
81
    return activityIndicatorView;
82
}
83

  
84
+ (id)activityIndicatorViewWithText:(NSString *)text withProgress:(BOOL)withProgress andAddToView:(UIView *)view {
85
    return [self activityIndicatorViewWithText:text withProgress:withProgress andAddToView:view scrollOffset:0.0];
86
}
87

  
88
+ (id)activityIndicatorViewWithText:(NSString *)text andAddToView:(UIView *)view scrollOffset:(CGFloat)offset {
89
    return [self activityIndicatorViewWithText:text withProgress:NO andAddToView:view scrollOffset:offset];
90
}
91

  
92
+ (id)activityIndicatorViewWithText:(NSString *)text andAddToView:(UIView *)view {
93
    return [self activityIndicatorViewWithText:text withProgress:NO andAddToView:view scrollOffset:0.0];
94
}
95

  
70 96
#pragma mark - View lifecycle
71 97

  
72 98
- (void)didMoveToSuperview {
......
118 144

  
119 145
- (void)removeFromSuperview {
120 146
    [self.spinner stopAnimating];
121
    self.superview.userInteractionEnabled = YES;
122 147
    [UIView animateWithDuration:kFadeTime animations:^{
123 148
        self.alpha = 0.0;
124
    }];
125
}
126

  
127
- (void)removeFromSuperviewAndRelease {
128
    [self.spinner stopAnimating];
129
    [UIView animateWithDuration:kFadeTime animations:^{
130
        self.alpha = 0.0;
131
    } completion:^(BOOL finished){
132
        // Check if just calling [self removeFromSuperview] suffices.
149
    } completion:^(BOOL finished) {
133 150
        self.superview.userInteractionEnabled = YES;
134
        [self release];
135
    }];
151
        [super removeFromSuperview];
152
    }];    
136 153
}
137 154

  
138 155
@end
b/Classes/AddFileViewController.h
6 6
//  Copyright 2011 __MyCompanyName__. All rights reserved.
7 7
//
8 8

  
9
#import <UIKit/UIKit.h>
10

  
11
@class OpenStackAccount, Container, Folder, ActivityIndicatorView, FolderViewController;
9
@class OpenStackAccount, Container, Folder, FolderViewController;
12 10

  
13 11
@interface AddFileViewController : UITableViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate, UIPopoverControllerDelegate> {
14 12
    UIImagePickerController *imagePicker;
......
17 15
    Container *container;
18 16
    Folder *folder;
19 17
    FolderViewController *folderViewController;
20
    ActivityIndicatorView *activityIndicatorView;
21 18
    id successObserver;
22 19
    id failureObserver;
23 20

  
b/Classes/AddFileViewController.m
17 17
#import "Folder.h"
18 18
#import "FolderViewController.h"
19 19
#import "StorageObject.h"
20
#import "ActivityIndicatorView.h"
21 20
#import "AddPhotoViewController.h"
22 21
#import "UploadGenericFileViewController.h"
23 22
#import "AddTextFileViewController.h"
b/Classes/AddFolderViewController.h
6 6
//  Copyright 2011 __MyCompanyName__. All rights reserved.
7 7
//
8 8

  
9
#import <UIKit/UIKit.h>
10

  
11
@class OpenStackAccount, Container, Folder, ActivityIndicatorView, FolderViewController;
9
@class OpenStackAccount, Container, Folder, FolderViewController;
12 10

  
13 11
@interface AddFolderViewController : UITableViewController <UITextFieldDelegate, UIAlertViewDelegate> {
14 12
    UITextField *textField;
15
    ActivityIndicatorView *activityIndicatorView;
16 13
    OpenStackAccount *account;
17 14
    Container *container;
18 15
    Folder *folder;
b/Classes/AddFolderViewController.m
79 79
                return;
80 80
            }
81 81

  
82
            NSString *activityMessage = @"Adding folder...";
83
            
84
            // figure out how many folders to create
85
            [activityIndicatorView release];
86
            activityIndicatorView = [[ActivityIndicatorView alloc] initWithText:activityMessage];
87
            [activityIndicatorView addToView:self.view];
88
            
89
            // actually create the folders
90 82
            StorageObject *object = [[StorageObject alloc] init];
91 83
            object.name = object.fullPath = objectName;
92 84
            object.data = [NSData data];
93 85
            object.contentType = @"application/directory";
94

  
86
            
87
            __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Adding folder..."
88
                                                                                                           andAddToView:self.view];
95 89
            [[self.account.manager writeObject:self.container object:object downloadProgressDelegate:nil]
96 90
             success:^(OpenStackRequest *request) {
97 91
                 Folder *newFolder = [[Folder alloc] init];
......
189 183
    [container release];
190 184
    [folder release];
191 185
    [folderViewController release];
192
    [activityIndicatorView release];
193 186
    [super dealloc];
194 187
}
195 188

  
b/Classes/AddObjectViewController.h
6 6
//  Copyright 2011 __MyCompanyName__. All rights reserved.
7 7
//
8 8

  
9
#import <UIKit/UIKit.h>
10

  
11
@class OpenStackAccount, Container, Folder, ActivityIndicatorView, FolderViewController;
9
@class OpenStackAccount, Container, Folder, FolderViewController;
12 10

  
13 11
@interface AddObjectViewController : UITableViewController {
14 12
    OpenStackAccount *account;
15 13
    Container *container;
16 14
    Folder *folder;
17
    ActivityIndicatorView *activityIndicatorView;
18 15
    FolderViewController *folderViewController;
19 16
    id successObserver;
20 17
    id failureObserver;
b/Classes/AddPhotoViewController.h
6 6
//  Copyright 2011 __MyCompanyName__. All rights reserved.
7 7
//
8 8

  
9
#import <UIKit/UIKit.h>
10

  
11 9
@class OpenStackAccount, Container, Folder, ActivityIndicatorView, FolderViewController;
12 10

  
13 11
@interface AddPhotoViewController : UITableViewController <UITextFieldDelegate, UIAlertViewDelegate> {
......
16 14
    Container *container;
17 15
    Folder *folder;
18 16
    FolderViewController *folderViewController;
19
    ActivityIndicatorView *activityIndicatorView;
20 17
    id successObserver;
21 18
    id failureObserver;
22 19

  
b/Classes/AddPhotoViewController.m
375 375
        [alert release];
376 376
        return;
377 377
    }
378
    [activityIndicatorView release];
379
    activityIndicatorView = [[ActivityIndicatorView alloc] initWithText:@"Uploading..." withProgress:YES];
380
    [activityIndicatorView addToView:self.view];
381 378

  
382 379
    StorageObject *object = [[StorageObject alloc] init];
383 380
    object.name = objectName;
384 381
    object.fullPath = [NSString stringWithFormat:@"%@/%@", [folder fullPath], object.name];
385 382
    object.fullPath = [object.fullPath substringFromIndex:1];
386
    
387 383
    if ([format isEqualToString:@".jpg"]) {
388 384
        object.contentType = @"image/jpeg";
389 385
    } else {
390 386
        object.contentType = @"image/png";
391 387
    }
392

  
393 388
    object.data = data;
394 389
    object.bytes = [data length];
395 390
    
391
    __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Uploading..."
392
                                                                                                   andAddToView:self.view];
396 393
    [[self.account.manager writeObject:self.container object:object downloadProgressDelegate:activityIndicatorView.progressView]
397 394
     success:^(OpenStackRequest *request) {
398 395
         [activityIndicatorView removeFromSuperview];
......
445 442
    [formatLabel release];
446 443
    [slider release];
447 444
    [qualityActivityIndicatorView release];
448
    [activityIndicatorView release];
449 445
    [super dealloc];
450 446
}
451 447

  
b/Classes/ContainerDetailViewController.h
6 6
//  The OpenStack project is provided under the Apache 2.0 license.
7 7
//
8 8

  
9
#import <UIKit/UIKit.h>
10

  
11
@class OpenStackAccount, Container, ActivityIndicatorView, ContainersViewController, FolderViewController;
9
@class OpenStackAccount, Container, ContainersViewController, FolderViewController;
12 10

  
13 11
@interface ContainerDetailViewController : UITableViewController <UIActionSheetDelegate> {
14 12
    OpenStackAccount *account;
15 13
    Container *container;
16 14
    ContainersViewController *containersViewController;
17 15
    FolderViewController *rootFolderViewController;
18
    ActivityIndicatorView *activityIndicatorView;
19 16
    id successObserver;
20 17
    id failureObserver;
21 18
    NSInteger deleteSection;
b/Classes/ContainerDetailViewController.m
17 17
#import "EditMetadataViewController.h"
18 18
#import "EditPolicyViewController.h"
19 19
#import "Folder.h"
20
#import "StorageObject.h"
20 21
#import "FolderViewController.h"
21 22
#import "OpenStackRequest.h"
22 23
#import "APICallback.h"
......
315 316

  
316 317
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
317 318
    if (buttonIndex == 0) {
318
     
319
        NSString *activityMessage = @"Deleting container...";
320
        [activityIndicatorView release];
321
        activityIndicatorView = [[ActivityIndicatorView alloc] initWithText:activityMessage];
322
        [activityIndicatorView addToView:self.view scrollOffset:self.tableView.contentOffset.y];  
323
        
324
        [[self.account.manager deleteContainer:self.container] success:^(OpenStackRequest *request) {
325
            
326
            [activityIndicatorView removeFromSuperview];                
327
            [self.account.containers removeObjectForKey:self.container.name];
328
            [self.account persist];
329
            if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
319
        __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Deleting container..."
320
                                                                                                       andAddToView:self.view
321
                                                                                                       scrollOffset:self.tableView.contentOffset.y];
322
        [[self.account.manager deleteContainer:self.container]
323
         success:^(OpenStackRequest *request) {
324
             [activityIndicatorView removeFromSuperview];
325
             [self.account.containers removeObjectForKey:self.container.name];
326
             [self.account persist];
327
             if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
330 328
                [self.containersViewController.navigationController popViewControllerAnimated:YES];
331
            else
329
             } else {
332 330
                [self.navigationController popViewControllerAnimated:YES];
333
            
334
            [self deleteContainerRow];
335

  
336
            
337
        } failure:^(OpenStackRequest *request) {
338
            
331
             }
332
             [self deleteContainerRow];
333
         }
334
         failure:^(OpenStackRequest *request) {
335
             [activityIndicatorView removeFromSuperview];
339 336
            // 404 Not Found means it's not there, so we can show the user that it's deleted
340 337
            if ([request responseStatusCode] == 404) {
341 338
                [self.account.containers removeObjectForKey:container.name];
342 339
                [self.account persist];
343
                
344 340
            } else {
345
                [activityIndicatorView removeFromSuperview];
346 341
                [self alert:@"There was a problem deleting this container." request:request];
347 342
            }
348
        }];
349
                    
343
         }];
350 344
    }
351 345
    [self.tableView deselectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:deleteSection] animated:YES];
352 346
}
......
361 355
    [containersViewController release];
362 356
    [selectedContainerIndexPath release];
363 357
    [rootFolderViewController release];
364
    [activityIndicatorView release];
365 358
    [super dealloc];
366 359
}
367 360

  
......
369 362
#pragma mark Helper functions
370 363

  
371 364
- (void)reloadMetadataSection {
372
    NSString *activityMessage = @"Loading metadata...";
373
    [activityIndicatorView release];
374
    activityIndicatorView = [[ActivityIndicatorView alloc] initWithText:activityMessage];
375
    [activityIndicatorView addToView:self.view scrollOffset:self.tableView.contentOffset.y]; 
376
    [[self.account.manager getContainerInfo:container] 
365
    __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Loading metadata..."
366
                                                                                                   andAddToView:self.view
367
                                                                                                   scrollOffset:self.tableView.contentOffset.y];
368
    [[self.account.manager getContainerInfo:container]
377 369
     success:^(OpenStackRequest *request) {
378 370
         [activityIndicatorView removeFromSuperview];
379 371
         container.metadata = [NSMutableDictionary dictionary];
b/Classes/EditAccountGroupsViewController.h
35 35
// interpreted as representing official policies, either expressed
36 36
// or implied, of GRNET S.A.
37 37

  
38
@class OpenStackAccount, ActivityIndicatorView;
38
@class OpenStackAccount;
39 39

  
40 40
@interface EditAccountGroupsViewController : UITableViewController <UITextFieldDelegate> {
41 41
    OpenStackAccount *account;
......
45 45
    NSMutableDictionary *metadata;
46 46
    
47 47
    BOOL removeGroupEnabled;
48
        
49
    ActivityIndicatorView *activityIndicatorView;
50 48
}
51 49

  
52 50
@property (nonatomic, retain) OpenStackAccount *account;
b/Classes/EditAccountGroupsViewController.m
67 67
    [account release];
68 68
    [metadata release];
69 69
    [groups release];
70
    [activityIndicatorView release];
71 70
    [super dealloc];
72 71
}
73 72

  
......
160 159
#pragma mark - UITableViewDelegate
161 160

  
162 161
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
163
    NSString *activityMessage;
164 162
    NSIndexPath *keyCellIndexPath;
165 163
    NSIndexPath *valueCellIndexPath;
166 164
    UITableViewCell *cell;
......
188 186
            [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
189 187
            return;
190 188
        }
191
                    
192
        activityMessage = @"Saving group";
193
        [activityIndicatorView release];
194
        activityIndicatorView = [[ActivityIndicatorView alloc] initWithText:activityMessage];
195
        [activityIndicatorView addToView:self.view];
196 189

  
197 190
        [groups removeObjectForKey:groupName];
198 191
        [groups setObject:newGroupUsers forKey:newGroupName];
......
200 193
                                        metadata, @"metadata",
201 194
                                        nil
202 195
                                        ];
203
        [[self.account.manager writeAccountMetadata:accountInfo] 
196
        __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Saving group..."
197
                                                                                                       andAddToView:self.view];
198
        [[self.account.manager writeAccountMetadata:accountInfo]
204 199
         success:^(OpenStackRequest *request) {
205 200
             [activityIndicatorView removeFromSuperview];
206 201
             self.groupName = newGroupName;
......
219 214
             [self alert:@"There was a problem saving the group information." request:request];
220 215
         }];
221 216
    } else if (indexPath.section == kRemove) {
222
        activityMessage = @"Removing group";
223
        [activityIndicatorView release];
224
        activityIndicatorView = [[ActivityIndicatorView alloc] initWithText:activityMessage];
225
        [activityIndicatorView addToView:self.view];
226
        
227 217
        [groups removeObjectForKey:groupName];
228 218
        NSDictionary *accountInfo = [NSDictionary dictionaryWithObjectsAndKeys:groups, @"groups",
229 219
                                        metadata, @"metadata",
230 220
                                        nil
231 221
                                        ];
232

  
233
        [[self.account.manager writeAccountMetadata:accountInfo] 
222
        __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Removing group..."
223
                                                                                                       andAddToView:self.view];
224
        [[self.account.manager writeAccountMetadata:accountInfo]
234 225
         success:^(OpenStackRequest *request) {
235 226
             [activityIndicatorView removeFromSuperview];
236 227
             self.groupName = @"";
b/Classes/EditMetadataViewController.h
35 35
// interpreted as representing official policies, either expressed
36 36
// or implied, of GRNET S.A.
37 37

  
38
#import <UIKit/UIKit.h>
39
#import "OpenStackAccount.h"
40
#import "Container.h"
41
#import "StorageObject.h"
42
#import "ActivityIndicatorView.h"
43

  
44
@class FolderViewController, OpenStackRequest;
38
@class FolderViewController, OpenStackRequest, OpenStackAccount, Container, StorageObject;
45 39

  
46 40
@interface EditMetadataViewController : UITableViewController <UITextFieldDelegate, UIAlertViewDelegate> {
47 41
    
......
54 48
    NSString *userInputMetaKey;
55 49
    NSString *userInputMetaValue;
56 50
    
57
    ActivityIndicatorView *activityIndicatorView;
58
    
59 51
    BOOL objectIsFolder;
60 52
    BOOL objectIsContainer;
61 53
    BOOL removeMetadataEnabled;
62
    
63 54
}
64 55

  
65 56
@property (nonatomic, retain) OpenStackAccount *account;
......
76 67
@property (nonatomic, assign) BOOL removeMetadataEnabled;
77 68
@property (nonatomic, retain) FolderViewController *folderViewController;
78 69

  
79
- (void)createNewFolder;
80

  
81 70
@end
b/Classes/EditMetadataViewController.m
39 39
#import "AccountManager.h"
40 40
#import "UIViewController+Conveniences.h"
41 41
#import "FolderViewController.h"
42
#import "OpenStackAccount.h"
43
#import "Container.h"
42 44
#import "Folder.h"
45
#import "StorageObject.h"
46
#import "ActivityIndicatorView.h"
43 47
#import "PithosUtilities.h"
44 48
#import "APICallback.h"
45 49

  
46

  
47

  
48 50
@implementation EditMetadataViewController
49 51

  
50

  
51 52
@synthesize container, account, object;
52 53

  
53 54
@synthesize metadataKey;
......
60 61
#define kDeleteMetadata 2
61 62

  
62 63

  
63
- (void)dealloc
64
{
64
- (void)dealloc {
65 65
    [account release];
66 66
    [container release];
67 67
    [object release];
......
69 69
    [metadataValue release];
70 70
    [userInputMetaKey release];
71 71
    [userInputMetaValue release];
72
    [activityIndicatorView release];
73 72
    [super dealloc];
74 73
}
75 74

  
76
- (void)didReceiveMemoryWarning
77
{
78
    // Releases the view if it doesn't have a superview.
79
    [super didReceiveMemoryWarning];
80
    
81
    // Release any cached data, images, etc that aren't in use.
82
}
83

  
84 75
#pragma mark - View lifecycle
85 76

  
86
- (void)viewDidLoad
87
{
88
    [super viewDidLoad];
89
}
90

  
91
- (void)viewDidUnload
92
{
93
    [super viewDidUnload];
94
}
95

  
96
- (void)viewWillAppear:(BOOL)animated
97
{    
98
    [super viewWillAppear:animated];
99
}
100

  
101
- (void)viewDidAppear:(BOOL)animated
102
{
103
    [super viewDidAppear:animated];
104
}
105

  
106
- (void)viewWillDisappear:(BOOL)animated
107
{
108
    [super viewWillDisappear:animated];
77
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
78
    return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait);
109 79
}
110 80

  
111
- (void)viewDidDisappear:(BOOL)animated
112
{
113
    [super viewDidDisappear:animated];
114
}
81
#pragma mark - Internal
115 82

  
116
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
117
    return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait);
83
- (void)createNewFolder {
84
    __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Saving metadata..."
85
                                                                                                   andAddToView:self.view];
86
    [[self.account.manager writeObject:container object:object downloadProgressDelegate:nil]
87
     success:^(OpenStackRequest *request) {
88
         Folder *newFolder = [[Folder alloc] init];
89
         newFolder.name = [[object.name componentsSeparatedByString:@"/"] lastObject];
90
         newFolder.parent = folderViewController.folder;
91
         newFolder.sharing = folderViewController.folder.sharing;
92
         newFolder.metadata = object.metadata;
93
         [folderViewController.folder addFolder:newFolder];
94
         [activityIndicatorView removeFromSuperview];
95
         [newFolder release];
96
         self.metadataKey = userInputMetaKey;
97
         self.metadataValue = userInputMetaValue;
98
         removeMetadataEnabled = YES;
99
         [self.tableView reloadData];
100
         [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
101
         if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
102
             [self.folderViewController refreshButtonPressed:nil];
103
         } else {
104
             self.folderViewController.needsRefreshing = YES;
105
             self.folderViewController.refreshWhenAppeared = YES;
106
         }
107
     }
108
     failure:^(OpenStackRequest *request) {
109
         [object.metadata removeObjectForKey:userInputMetaKey];
110
         [object.metadata setObject:metadataValue forKey:metadataKey];
111
         [activityIndicatorView removeFromSuperview];
112
         [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
113
         [self.tableView reloadData];
114
         [self alert:@"There was a problem saving the metadata." request:request];
115
     }];
118 116
}
119 117

  
120 118
#pragma mark - Table view data source
121 119

  
122
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
123
{
124
    return (removeMetadataEnabled)? 3:2;
120
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
121
    return (removeMetadataEnabled ? 3 : 2);
125 122
}
126 123

  
127
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
128
{
129
    if (section == kMetadata)
130
        return 2;
131
    else
132
        return 1;
124
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
125
    return ((section == kMetadata) ? 2 : 1);
133 126
}
134 127

  
135
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
136
{
128
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
137 129
    static NSString *CellIdentifier = @"Cell";
138 130
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
139 131
    if (cell == nil) {
......
167 159
            textField.placeholder = @"Key";
168 160
            textField.text = self.metadataKey;
169 161
            textField.tag = 0;
170
        }
171
        else if (indexPath.row == 1) {
162
        } else if (indexPath.row == 1) {
172 163
            textField.placeholder = @"Value";
173 164
            textField.text = self.metadataValue;
174 165
            textField.tag = 1;
......
176 167
            
177 168
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
178 169
        [cell.contentView addSubview:textField];
179
    }
180
    else if (indexPath.section == kSaveMedata) 
170
    } else if (indexPath.section == kSaveMedata) {
181 171
        cell.textLabel.text = @"Save";
182
    else if (indexPath.section == kDeleteMetadata)
172
    } else if (indexPath.section == kDeleteMetadata) {
183 173
        cell.textLabel.text = @"Remove";
184
    
174
    }
175

  
185 176
    return cell;
186 177
}
187 178

  
188

  
189 179
#pragma mark - Table view delegate
190 180

  
191
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
192
{
193

  
194
    
181
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
195 182
    if (indexPath.section != kMetadata)
196 183
        [self.view endEditing:YES];
197 184
    
198
    NSString *activityMessage;
199 185
    NSIndexPath *keyCellIndexPath;
200 186
    NSIndexPath *valueCellIndexPath;
201 187
    UITableViewCell *cell;
202 188
    
203
    switch (indexPath.section) {
204
        case kSaveMedata:
205
            keyCellIndexPath = [NSIndexPath indexPathForRow:0 inSection:kMetadata];
206
            cell = [self.tableView cellForRowAtIndexPath:keyCellIndexPath];
207
            UITextField *textField = [[cell.contentView subviews] objectAtIndex:0];
208
            self.userInputMetaKey = textField.text;
209
        
210
            if ([userInputMetaKey length] == 0
211
                || [[userInputMetaKey stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0) {
212
                [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
213
                [self alert:@"Invalid input" message:@"Metadata key cannot be empty"];
214
                return;
215
            }
216
            
189
    if (indexPath.section == kSaveMedata) {
190
        keyCellIndexPath = [NSIndexPath indexPathForRow:0 inSection:kMetadata];
191
        cell = [self.tableView cellForRowAtIndexPath:keyCellIndexPath];
192
        UITextField *textField = [[cell.contentView subviews] objectAtIndex:0];
193
        self.userInputMetaKey = textField.text;
194
    
195
        if (!userInputMetaKey.length || ![userInputMetaKey stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]].length) {
196
            [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
197
            [self alert:@"Invalid input" message:@"Metadata key cannot be empty"];
198
        } else {
217 199
            valueCellIndexPath = [NSIndexPath indexPathForRow:1 inSection:kMetadata];
218 200
            cell = [self.tableView cellForRowAtIndexPath:valueCellIndexPath];
219 201
            textField = [[cell.contentView subviews] objectAtIndex:0];
......
223 205
            
224 206
            if (objectIsFolder && ![PithosUtilities isContentTypeDirectory:object.contentType]) {
225 207
                if (((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) &&
226
                     [folderViewController.parentFolderViewController.folder.objects objectForKey:object.name]) || 
208
                     [folderViewController.parentFolderViewController.folder.objects objectForKey:object.name]) ||
227 209
                    ((UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad) &&
228 210
                     [folderViewController.folder.objects objectForKey:object.name])) {
229
                    NSString *alertMessage = [NSString stringWithFormat:@"In order to apply the changes in '%@', the object at the same path must be replaced. Continue?",object.name];
211
                    NSString *alertMessage = [NSString stringWithFormat:@"In order to apply the changes in '%@', the object at the same path must be replaced. Continue?", object.name];
230 212
                    NSString *alertTitle = @"Apply changes";
231 213
                    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:alertTitle
232 214
                                                                    message:alertMessage
......
235 217
                                                          otherButtonTitles:@"OK", nil];
236 218
                    [alert show];
237 219
                    [alert release];
238
                    return;
239 220
                } else {
240
                    activityMessage = @"Saving metadata...";
241
                    [activityIndicatorView release];
242
                    activityIndicatorView = [[ActivityIndicatorView alloc] initWithText:activityMessage];
243
                    [activityIndicatorView addToView:self.view];
244
                    
245 221
                    object.name = object.fullPath;
246 222
                    object.contentType = @"application/directory";
247 223
                    object.data = [NSData data];
248 224
                    [self createNewFolder];
249
                    return;
250 225
                }
251
            }
252
            
253
            activityMessage = @"Saving metadata";
254
            [activityIndicatorView release];
255
            activityIndicatorView = [[ActivityIndicatorView alloc] initWithText:activityMessage];
256
            [activityIndicatorView addToView:self.view];
257
            [[self.account.manager writeObjectMetadata:container object:object] 
258
             success:^(OpenStackRequest *request) {
259
                 self.metadataKey = userInputMetaKey;
260
                 self.metadataValue = userInputMetaValue;
261
                 removeMetadataEnabled = YES;
262
                 [self.tableView reloadData];
263
                 [activityIndicatorView removeFromSuperview];
264
                 [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
265
                 if (objectIsContainer) {
266
                     container.metadata = object.metadata;
267
                     [self.account.containers setObject:container forKey:container.name];
226
            } else {
227
                __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Saving metadata..."
228
                                                                                                               andAddToView:self.view];
229
                [[self.account.manager writeObjectMetadata:container object:object]
230
                 success:^(OpenStackRequest *request) {
231
                     self.metadataKey = userInputMetaKey;
232
                     self.metadataValue = userInputMetaValue;
233
                     removeMetadataEnabled = YES;
234
                     [self.tableView reloadData];
235
                     [activityIndicatorView removeFromSuperview];
236
                     [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
237
                     if (objectIsContainer) {
238
                         container.metadata = object.metadata;
239
                         [self.account.containers setObject:container forKey:container.name];
240
                     }
268 241
                 }
269
             }
270
             failure:^(OpenStackRequest *request) { 
271
                 [object.metadata removeObjectForKey:userInputMetaKey];
272
                 [object.metadata setObject:metadataValue forKey:metadataKey];
273
                 [activityIndicatorView removeFromSuperview];
274
                 [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
275
                 [self alert:@"There was a problem saving the metadata." request:request];
276
             }];
277
                        
278
            break;
279
        case kDeleteMetadata:
280
            activityMessage = @"Deleting metadata";
281
            [activityIndicatorView release];
282
            activityIndicatorView = [[ActivityIndicatorView alloc] initWithText:activityMessage];
283
            [activityIndicatorView addToView:self.view];
284

  
242
                 failure:^(OpenStackRequest *request) { 
243
                     [object.metadata removeObjectForKey:userInputMetaKey];
244
                     [object.metadata setObject:metadataValue forKey:metadataKey];
245
                     [activityIndicatorView removeFromSuperview];
246
                     [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
247
                     [self alert:@"There was a problem saving the metadata." request:request];
248
                 }];
249
            }
250
        }
251
    } else if (indexPath.section == kDeleteMetadata) {
252
        __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Deleting metadata..."
253
                                                                                                       andAddToView:self.view];
285 254
            [object.metadata removeObjectForKey:metadataKey];
286
            [[self.account.manager writeObjectMetadata:container object:object] 
255
            [[self.account.manager writeObjectMetadata:container object:object]
287 256
             success:^(OpenStackRequest *request) {
288 257
                 [activityIndicatorView removeFromSuperview];
289 258
                 [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
......
303 272
                 [self alert:@"There was a problem saving the metadata." request:request];
304 273

  
305 274
             }];
306
            break;
307 275
    }
308 276
}
309 277

  
310 278
#pragma mark - Alertview delegate
311 279

  
312
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
313
{
280
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
314 281
    if (buttonIndex == 1) {
315
        NSString *activityMessage = @"Applying permissions...";
316
        [activityIndicatorView release];
317
        activityIndicatorView = [[ActivityIndicatorView alloc] initWithText:activityMessage];
318
        [activityIndicatorView addToView:self.view];
319
        
320 282
        object.name = object.fullPath;
321 283
        object.contentType = @"application/directory";
322 284
        object.data = [NSData data];
......
328 290

  
329 291
#pragma mark - Textfield delegate
330 292

  
331

  
332
- (BOOL)textFieldShouldReturn:(UITextField *)textField
333
{
334
    
335
    if ([textField returnKeyType] == UIReturnKeyNext)
336
    {
337
        if ([textField.text length] == 0
338
            || [[textField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0) {
293
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
294
    if ([textField returnKeyType] == UIReturnKeyNext) {
295
        if (!textField.text.length || ![textField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]) {
339 296
            [self alert:@"Invalid input" message:@"Metadata key cannot be empty"];
340 297
        }
341 298

  
342 299
        NSInteger nextTag = [textField tag] + 1;
343 300
        UIView *nextTextField = [self.tableView viewWithTag:nextTag];
344 301
        [nextTextField becomeFirstResponder];
345
    }
346
    else
347
    {
302
    } else {
348 303
        [textField resignFirstResponder];
349 304
    }
350 305
    
351 306
    return YES;
352 307
}
353 308

  
354
#pragma mark - add observers
355

  
356
- (void)createNewFolder {
357
    [[self.account.manager writeObject:container object:object downloadProgressDelegate:nil] 
358
     success:^(OpenStackRequest *request) {
359
         Folder *newFolder = [[Folder alloc] init];
360
         newFolder.name = [[object.name componentsSeparatedByString:@"/"] lastObject];
361
         newFolder.parent = folderViewController.folder;
362
         newFolder.sharing = folderViewController.folder.sharing;
363
         newFolder.metadata = object.metadata;
364
         [folderViewController.folder addFolder:newFolder];
365
         [activityIndicatorView removeFromSuperview];
366
         [newFolder release];
367
         self.metadataKey = userInputMetaKey;
368
         self.metadataValue = userInputMetaValue;
369
         removeMetadataEnabled = YES;
370
         [self.tableView reloadData];
371
         [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
372
         if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
373
             [self.folderViewController refreshButtonPressed:nil];
374
         } else {
375
             self.folderViewController.needsRefreshing = YES;
376
             self.folderViewController.refreshWhenAppeared = YES;
377
         }
378
     }
379
     failure:^(OpenStackRequest *request) {
380
         [object.metadata removeObjectForKey:userInputMetaKey];
381
         [object.metadata setObject:metadataValue forKey:metadataKey];
382
         [activityIndicatorView removeFromSuperview];
383
         [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
384
         [self.tableView reloadData];
385
         [self alert:@"There was a problem saving the metadata." request:request];
386
     }];
387
}
388

  
389 309
@end
b/Classes/EditPermissionsViewController.h
36 36
// or implied, of GRNET S.A.
37 37

  
38 38
#import <UIKit/UIKit.h>
39
#import "OpenStackAccount.h"
40
#import "Container.h"
41
#import "StorageObject.h"
42
#import "ActivityIndicatorView.h"
43 39

  
44
@class FolderViewController, OpenStackRequest;
40
@class FolderViewController, OpenStackRequest, OpenStackAccount, Container, StorageObject;
45 41

  
46 42
@interface EditPermissionsViewController : UITableViewController <UITextFieldDelegate, UIAlertViewDelegate> {
47 43
    NSString *user;
......
53 49
    Container *container;
54 50
    StorageObject *object;
55 51
    
56
    ActivityIndicatorView *activityIndicatorView;
57
        
58 52
    NSString *oldPermissionsString;
59 53
    BOOL newPermissionsEntry;
60 54
    BOOL removePermissionsEnabled;
61 55
    BOOL objectIsFolder;
62
    
63
        
64 56
}
65 57

  
66 58
@property (nonatomic, retain) OpenStackAccount *account;
......
77 69
@property (nonatomic, assign) FolderViewController *folderViewController; 
78 70
@property (nonatomic, assign) BOOL objectIsFolder;
79 71

  
80
-(void)createNewFolder;
81

  
82
// Helper methods
83
- (NSString *)buildPermissionsString;
84
- (BOOL)userInputIsValid:(NSString *)input;
85

  
86 72
@end
b/Classes/EditPermissionsViewController.m
39 39
#import "AccountManager.h"
40 40
#import "UIViewController+Conveniences.h"
41 41
#import "FolderViewController.h"
42
#import "OpenStackAccount.h"
43
#import "Container.h"
42 44
#import "Folder.h"
45
#import "StorageObject.h"
46
#import "ActivityIndicatorView.h"
43 47
#import "PithosUtilities.h"
44 48
#import "APICallback.h"
45 49

  
......
56 60
@synthesize newPermissionsEntry, removePermissionsEnabled;
57 61
@synthesize folderViewController, objectIsFolder;
58 62

  
59
- (void)dealloc
60
{
63
- (void)dealloc {
61 64
    [account release];
62 65
    [container release];
63 66
    [object release];
64 67
    [user release];
65 68
    [permissions release];
66 69
    [oldPermissionsString release];
67
    [activityIndicatorView release];
68 70
    [super dealloc];
69 71
}
70 72

  
71
- (void)didReceiveMemoryWarning
72
{
73
    // Releases the view if it doesn't have a superview.
74
    [super didReceiveMemoryWarning];
75
    
76
    // Release any cached data, images, etc that aren't in use.
77
}
78

  
79 73
#pragma mark - View lifecycle
80 74

  
81
- (void)viewDidLoad
82
{
83
    [super viewDidLoad];
84
}
85

  
86
- (void)viewDidUnload
87
{
88
    [super viewDidUnload];
89
}
90

  
91
- (void)viewWillAppear:(BOOL)animated
92
{
93
    [super viewWillAppear:animated];
75
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
76
    return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait);
94 77
}
95 78

  
96
- (void)viewDidAppear:(BOOL)animated
97
{
98
    [super viewDidAppear:animated];
99
}
79
#pragma mark - Internal
100 80

  
101
- (void)viewWillDisappear:(BOOL)animated
102
{
103
    [super viewWillDisappear:animated];
81
- (NSString *)buildPermissionsString {
82
    NSString *readPermissionsString = @"";
83
    NSString *writePermissionsString = @"";
84
    for (NSString *aUser in [permissions allKeys]) {
85
        if ([[permissions objectForKey:aUser] isEqual:@"read"]) {
86
            if (!readPermissionsString.length) {
87
                readPermissionsString = [NSString stringWithFormat:@"read=%@", aUser];
88
            } else {
89
                readPermissionsString = [NSString stringWithFormat:@"%@,%@", readPermissionsString ,aUser];
90
            }
91
        } else if ([[permissions objectForKey:aUser] isEqual:@"write"]) {
92
            if (!writePermissionsString.length) {
93
                writePermissionsString = [NSString stringWithFormat:@"write=%@", aUser];
94
            } else {
95
                writePermissionsString = [NSString stringWithFormat:@"%@,%@", writePermissionsString, aUser];
96
            }
97
        }
98
    }
99
    if (!writePermissionsString.length)
100
        return readPermissionsString;
101
    if (!readPermissionsString.length)
102
        return writePermissionsString;
103
    return [NSString stringWithFormat:@"%@;%@", readPermissionsString, writePermissionsString];
104 104
}
105 105

  
106
- (void)viewDidDisappear:(BOOL)animated
107
{
108
    [super viewDidDisappear:animated];
106
- (BOOL)userInputIsValid:(NSString *)input {
107
    if (!input.length || ![input stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]].length) {
108
        [self alert:@"Invalid input" message:@"User name cannot be empty"];
109
        return NO;
110
    }
111
    NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:@"=,;"];
112
    if ([input rangeOfCharacterFromSet:set].location != NSNotFound) {
113
        [self alert:@"Invalid input" message:@"User name cannot contain '=', ',' or ';'"];
114
        return NO;
115
    }
116
    return YES;
109 117
}
110 118

  
111
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
112
    return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait);
119
- (void)createNewFolder {
120
    __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Applying permissions..."
121
                                                                                                   andAddToView:self.view];
122
    [[self.account.manager writeObject:self.container object:object downloadProgressDelegate:nil]
123
     success:^(OpenStackRequest *request) {
124
         Folder *newFolder = [[Folder alloc] init];
125
         newFolder.name = [[object.name componentsSeparatedByString:@"/"] lastObject];
126
         newFolder.parent = folderViewController.folder;
127
         newFolder.sharing = folderViewController.folder.sharing;
128
         [folderViewController.folder addFolder:newFolder];
129
         [activityIndicatorView removeFromSuperview];
130
         [newFolder release];
131
         [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
132
         removePermissionsEnabled = YES;
133
         [self.tableView reloadData];
134
         if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
135
             [self.folderViewController refreshButtonPressed:nil];
136
         } else {
137
             self.folderViewController.needsRefreshing = YES;
138
             self.folderViewController.refreshWhenAppeared = YES;
139
         }
140
     }
141
     failure:^(OpenStackRequest *request) {
142
         object.sharing = self.oldPermissionsString;
143
         readPermissionSelected = !readPermissionSelected;
144
         writePermissionSelected = !writePermissionSelected;
145
         
146
         if (readPermissionSelected)
147
             [self.permissions setObject:@"read" forKey:user];
148
         else if (writePermissionSelected)
149
             [self.permissions setObject:@"write" forKey:user];
150
         
151
         [activityIndicatorView removeFromSuperview];
152
         [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
153
         [self.tableView reloadData];
154
         [self alert:@"There was a problem applying the permissions." request:request];
155
     }];
113 156
}
114 157

  
115 158
#pragma mark - Table view data source
116 159

  
117
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
118
{
119
    if (removePermissionsEnabled)
120
        return 4;
121
    else 
122
        return 3;
160
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
161
    return (removePermissionsEnabled ? 4 : 3);
123 162
}
124 163

  
125
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
126
{
127
    if (section == kPermissions)
128
        return 2;
129
    else
130
        return 1;
164
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
165
    return ((section == kPermissions) ? 2 : 1);
131 166
}
132 167

  
133
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
134
{
168
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
135 169
    static NSString *CellIdentifier = @"Cell";
136 170
    
137 171
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
......
167 201
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
168 202
        [cell.contentView addSubview:textField];
169 203
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
170
    }
171
    else if (indexPath.section == kPermissions) {
204
    } else if (indexPath.section == kPermissions) {
172 205
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
173 206
        if (indexPath.row == 0) {
174 207
            cell.textLabel.text = @"Read Only";
......
176 209
                cell.accessoryType = UITableViewCellAccessoryCheckmark;
177 210
            else
178 211
                cell.accessoryType = UITableViewCellAccessoryNone;
179
        }
180
        else {
212
        } else {
181 213
            cell.textLabel.text = @"Read/Write";
182 214
            if (writePermissionSelected)
183 215
                cell.accessoryType = UITableViewCellAccessoryCheckmark;
184 216
            else
185 217
                cell.accessoryType = UITableViewCellAccessoryNone;
186 218
        }
187
    } 
188
    else if (indexPath.section == kSavePermissions) {
219
    } else if (indexPath.section == kSavePermissions) {
189 220
        cell.textLabel.text = @"Save";
190 221
        cell.accessoryType = UITableViewCellAccessoryNone;
191 222
        cell.selectionStyle = UITableViewCellSelectionStyleBlue;
192
    }
193
    else if (indexPath.section == kRemovePermissions) {
223
    } else if (indexPath.section == kRemovePermissions) {
194 224
        cell.textLabel.text = @"Remove";
195 225
        cell.accessoryType = UITableViewCellAccessoryNone;
196 226
        cell.selectionStyle = UITableViewCellSelectionStyleBlue;
......
201 231

  
202 232
#pragma mark - Table view delegate
203 233

  
204
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
205
{    
206
    
234
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
207 235
    if (indexPath.section != kUser)
208 236
        [self.view endEditing:YES];
209 237
    
......
214 242
    newUserName = textField.text;
215 243
    if (![self userInputIsValid:newUserName]) {
216 244
        [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
217
        return;
218
    }
219
    
220
    if (indexPath.section == kPermissions) {
245
    } else if (indexPath.section == kPermissions) {
221 246
        UITableViewCell *readPermissionsCell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:kPermissions]];
222 247
        UITableViewCell *writePermissionsCell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:kPermissions]];
223 248

  
......
230 255
                }
231 256
                readPermissionsCell.accessoryType = UITableViewCellAccessoryCheckmark;
232 257
            }
233
        }
234
        else if (indexPath.row == 1) {
258
        } else if (indexPath.row == 1) {
235 259
            if (!writePermissionSelected) {
236 260
                writePermissionSelected = YES;
237 261
                if (readPermissionSelected) {
......
241 265
                writePermissionsCell.accessoryType = UITableViewCellAccessoryCheckmark;
242 266
            }
243 267
        }
244
    }
245
    else if (indexPath.section == kSavePermissions) {
268
    } else if (indexPath.section == kSavePermissions) {
246 269
        if (!readPermissionSelected && !writePermissionSelected) {
247 270
            [self alert:@"Cannot save permissions"  message:@"Please select permissions type"];
248 271
            [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff