Statistics
| Branch: | Tag: | Revision:

root / Classes / ContainerDetailViewController.m @ c2940e36

History | View | Annotate | Download (15.5 kB)

1
//
2
//  ContainerDetailViewController.m
3
//  OpenStack
4
//
5
//  Created by Mike Mayo on 12/22/10.
6
//  The OpenStack project is provided under the Apache 2.0 license.
7
//
8

    
9
#import "ContainerDetailViewController.h"
10
#import "OpenStackAccount.h"
11
#import "Container.h"
12
#import "ActivityIndicatorView.h"
13
#import "AccountManager.h"
14
#import "UIViewController+Conveniences.h"
15
#import "UIColor+MoreColors.h"
16
#import "ContainersViewController.h"
17
#import "EditMetadataViewController.h"
18
#import "EditPolicyViewController.h"
19
#import "Folder.h"
20
#import "StorageObject.h"
21
#import "FolderViewController.h"
22
#import "OpenStackRequest.h"
23
#import "APICallback.h"
24
#import "NSString+Conveniences.h"
25

    
26
#define kOverview 0
27
#define kMetadata 1
28

    
29
#define maxMetadataViewableLength 12
30

    
31
@implementation ContainerDetailViewController
32

    
33
@synthesize account, container, containersViewController, selectedContainerIndexPath, rootFolderViewController;
34

    
35
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
36
    return ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait);
37
}
38

    
39
- (void)setBackgroundView {
40
    if (!self.container) {
41
        UIView *viewContainer = [[UIView alloc] init];
42
        viewContainer.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
43
        viewContainer.backgroundColor = [UIColor iPadTableBackgroundColor];
44
        
45
        UILabel *label = [[UILabel alloc] init];
46
        label.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
47
        label.backgroundColor = [UIColor clearColor];
48
        label.textColor = [UIColor emptyCollectionGrayColor];
49
        label.font = [UIFont boldSystemFontOfSize:18.0];
50
        label.text = @"No container selected";
51
        label.textAlignment = UITextAlignmentCenter;
52
        [viewContainer addSubview:label];
53
        [label release];
54
        
55
        self.tableView.backgroundView = viewContainer;
56
        [viewContainer release];
57
    }
58
}
59

    
60
#pragma mark -
61
#pragma mark View lifecycle
62

    
63
- (void)viewDidLoad {
64
    [super viewDidLoad];
65
    if (!account.sharingAccount) {
66
        deleteSection = 3;
67
        policySection = 2;
68
    } else {
69
        deleteSection = -1;
70
        policySection = -1;
71
    }
72
}
73

    
74
- (void)viewWillAppear:(BOOL)animated {
75
    [super viewWillAppear:animated];
76
    if (container) {
77
        self.navigationItem.title = container.name;
78
    } 
79
    [self setBackgroundView];
80
    [self.tableView reloadData];
81
}
82

    
83
- (void)viewDidAppear:(BOOL)animated {
84
    [super viewDidAppear:animated];
85
    if (self.container && !container.metadata && ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPhone))
86
        [self reloadMetadataSection];
87
}
88

    
89
- (void)viewWillDisappear:(BOOL)animated {
90
    [super viewWillDisappear:animated];
91
}
92

    
93
#pragma mark -
94
#pragma mark Table view data source
95

    
96
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
97
    if (section == deleteSection) {
98
        return @"Only empty containers can be deleted.";
99
    } else {
100
        return @"";
101
    }
102
}
103

    
104
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
105
    if (self.container) {
106
        if (account.sharingAccount)
107
            return 2;
108
        else
109
            return 4;
110
    } else {
111
        return 0;
112
    }
113
}
114

    
115
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
116
    // Return the number of rows in the section.
117
    if (section == kOverview) {
118
        return 2;
119
    } else if (section == kMetadata) {
120
        if (account.sharingAccount)
121
            return [container.metadata count];
122
        else
123
            return 1 + [container.metadata count];     
124
    } else if (section == policySection) {
125
        if (account.sharingAccount)
126
            return 2;
127
        else
128
            return 3;
129
    } else {
130
        return 1;
131
    }
132
}
133

    
134
// Customize the appearance of table view cells.
135
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
136
    if (indexPath.section == deleteSection) {
137
        static NSString *CellIdentifier = @"DeleteCell";
138
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
139
        if (cell == nil) {
140
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
141
            cell.textLabel.textAlignment = UITextAlignmentCenter;
142
            cell.textLabel.text = @"Delete Container";
143
        }
144
        if ((self.container.count == 0) ||
145
            (self.container.rootFolder && !self.container.rootFolder.objectsAndFoldersCount)) {
146
            cell.textLabel.textColor = [UIColor blackColor];
147
            cell.selectionStyle = UITableViewCellSelectionStyleBlue;
148
        } else {
149
            cell.textLabel.textColor = [UIColor grayColor];
150
            cell.selectionStyle = UITableViewCellSelectionStyleNone;
151
            cell.userInteractionEnabled = NO;
152
        }
153
        return cell;
154
    }
155

    
156
    static NSString *CellIdentifier = @"Cell";
157
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
158
    if (cell == nil) {
159
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
160
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
161
        cell.textLabel.backgroundColor = [UIColor clearColor];
162
        cell.detailTextLabel.backgroundColor = [UIColor clearColor];
163
        cell.detailTextLabel.numberOfLines = 0;
164
        cell.detailTextLabel.lineBreakMode = UILineBreakModeWordWrap;
165
        cell.detailTextLabel.textAlignment = UITextAlignmentLeft;
166
    }
167
    cell.accessoryType = UITableViewCellAccessoryNone;
168
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
169
    
170
    if (indexPath.section == kOverview) {
171
        cell.accessoryView = nil;
172
        if (indexPath.row == 0) {
173
            cell.textLabel.text = @"Name";
174
            cell.detailTextLabel.text = container.name;
175
        } else if (indexPath.row == 1) {
176
            cell.textLabel.text = @"Size";
177
            cell.detailTextLabel.text = [container humanizedSize];
178
        }
179
    } else if (indexPath.section == kMetadata) {
180
        if (account.sharingAccount) {
181
            cell.accessoryType = UITableViewCellAccessoryNone;
182
            cell.selectionStyle = UITableViewCellSelectionStyleNone;
183
            cell.userInteractionEnabled = NO;
184
        }
185
        else {
186
            cell.selectionStyle = UITableViewCellSelectionStyleBlue;
187
            cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
188
        }
189
        if (indexPath.row == [container.metadata count]) {
190
            cell.textLabel.text = @"Add Metadata";
191
            cell.detailTextLabel.text = @"";
192
        } else {
193
            NSString *key = [[container.metadata allKeys] objectAtIndex:indexPath.row];
194
            NSString *value = [container.metadata objectForKey:key];
195
            NSString *metadataKeyCellText = key;
196
            NSString *metadataValueCellText = value;
197
            if ([metadataKeyCellText length] > maxMetadataViewableLength) {
198
                metadataKeyCellText = [metadataKeyCellText substringToIndex:(maxMetadataViewableLength - 3)];
199
                metadataKeyCellText = [metadataKeyCellText stringByAppendingString:@"..."];
200
            }
201
            if ([metadataValueCellText length] > maxMetadataViewableLength) {
202
                metadataValueCellText = [metadataValueCellText substringToIndex:(maxMetadataViewableLength - 3)];
203
                metadataValueCellText = [metadataValueCellText stringByAppendingString:@"..."];
204
            }
205
            cell.textLabel.text = metadataKeyCellText;
206
            cell.detailTextLabel.text = metadataValueCellText;
207
        }
208
    } else if (indexPath.section == policySection) {
209
        cell.selectionStyle = UITableViewCellSelectionStyleBlue;
210
        if (indexPath.row == 0) {
211
            cell.textLabel.text = @"Versioning";
212
            cell.detailTextLabel.text = container.versioning;
213
            cell.accessoryType = UITableViewCellAccessoryNone;
214
            cell.selectionStyle = UITableViewCellSelectionStyleNone;
215
        }
216
        else if (indexPath.row == 1) {
217
            cell.textLabel.text = @"Quota";
218
            cell.detailTextLabel.text = [NSString stringWithFormat:@"%u", container.quota];
219
            cell.accessoryType = UITableViewCellAccessoryNone;
220
            cell.selectionStyle = UITableViewCellSelectionStyleNone;
221
        }
222
        else {
223
            cell.textLabel.text = @"Edit policy";
224
            cell.detailTextLabel.text = @"";
225
            cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
226
        }
227
    }
228
    
229
    return cell;
230
}
231

    
232
#pragma mark -
233
#pragma mark Table view delegate
234

    
235
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
236
    
237
    if (indexPath.section == kMetadata) {
238
        EditMetadataViewController *vc = [[EditMetadataViewController alloc] initWithNibName:@"EditMetadataViewController" bundle:nil];
239
        NSString *metadataKey;
240
        NSString *metadataValue;
241
        
242
        if (indexPath.row == [self.container.metadata count]) {
243
            metadataKey = @"";
244
            metadataValue = @"";
245
            vc.removeMetadataEnabled = FALSE;
246
            vc.navigationItem.title = @"Add Metadata";
247
        }
248
        else {
249
            metadataKey = [[self.container.metadata allKeys] objectAtIndex:indexPath.row];
250
            metadataValue = [self.container.metadata objectForKey:metadataKey];
251
            vc.removeMetadataEnabled = TRUE;
252
            vc.navigationItem.title = @"Edit Metadata";
253
        }
254
        
255
        StorageObject *object = [[[StorageObject alloc] init] autorelease];
256
        object.name = container.name;
257
        object.metadata = container.metadata;
258
        object.fullPath = @"";
259
        
260
        vc.metadataKey = metadataKey;
261
        vc.metadataValue = metadataValue;
262
        vc.account = account;
263
        vc.container = container;
264
        vc.object = object;
265
        vc.objectIsContainer = YES;
266
        
267
        [self.navigationController pushViewController:vc animated:YES];
268
        [vc release];
269
    } else if (indexPath.section == policySection) {
270
        if (indexPath.row == 2) {
271
            EditPolicyViewController *vc = [[EditPolicyViewController alloc] initWithNibName:@"EditPolicyViewController" bundle:nil];
272
    
273
            vc.account = account;
274
            vc.container = container;
275
            vc.containerDetailViewController = self;
276
        
277
            [self.navigationController pushViewController:vc animated:YES];
278
            [vc release];
279
        }
280
    } else if (indexPath.section == deleteSection) {
281
        if (self.container.count == 0 || !self.container.rootFolder.objectsAndFoldersCount) {
282
            UIActionSheet *deleteActionSheet = [[[UIActionSheet alloc] initWithTitle:@"Are you sure you want to delete this container? This operation cannot be undone."
283
                                                                            delegate:self
284
                                                                   cancelButtonTitle:@"Cancel"
285
                                                              destructiveButtonTitle:@"Delete Container"
286
                                                                   otherButtonTitles:nil] autorelease];
287
            [deleteActionSheet showInView:self.view];
288
        }
289
    }
290
}
291

    
292
#pragma mark -
293
#pragma mark Action Sheet
294

    
295
- (void)deleteContainerRow {
296
    if ([self.account.containers count] == 0) {
297
        [self.containersViewController.tableView reloadData];
298
    } else {
299
        [self.containersViewController.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:selectedContainerIndexPath] withRowAnimation:UITableViewRowAnimationLeft];
300
    }
301
    [self.rootFolderViewController.navigationController popViewControllerAnimated:YES];
302
}
303

    
304
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
305
    if (buttonIndex == 0) {
306
        __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Deleting container..."
307
                                                                                                       andAddToView:self.view
308
                                                                                                       scrollOffset:self.tableView.contentOffset.y];
309
        [[self.account.manager deleteContainer:self.container]
310
         success:^(OpenStackRequest *request) {
311
             [activityIndicatorView stopAnimatingAndRemoveFromSuperview];
312
             [self.account.containers removeObjectForKey:self.container.name];
313
             [self.account persist];
314
             if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
315
                [self.containersViewController.navigationController popViewControllerAnimated:YES];
316
             } else {
317
                [self.navigationController popViewControllerAnimated:YES];
318
             }
319
             [self deleteContainerRow];
320
         }
321
         failure:^(OpenStackRequest *request) {
322
             [activityIndicatorView stopAnimatingAndRemoveFromSuperview];
323
            // 404 Not Found means it's not there, so we can show the user that it's deleted
324
            if ([request responseStatusCode] == 404) {
325
                [self.account.containers removeObjectForKey:container.name];
326
                [self.account persist];
327
            } else {
328
                [self alert:@"There was a problem deleting this container." request:request];
329
            }
330
         }];
331
    }
332
    [self.tableView deselectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:deleteSection] animated:YES];
333
}
334

    
335

    
336
#pragma mark -
337
#pragma mark Memory management
338

    
339
- (void)dealloc {
340
    [account release];
341
    [container release];
342
    [containersViewController release];
343
    [selectedContainerIndexPath release];
344
    [rootFolderViewController release];
345
    [super dealloc];
346
}
347

    
348
#pragma mark -
349
#pragma mark Helper functions
350

    
351
- (void)reloadMetadataSection {
352
    __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Loading metadata..."
353
                                                                                                   andAddToView:self.view
354
                                                                                                   scrollOffset:self.tableView.contentOffset.y];
355
    [[self.account.manager getContainerInfo:container]
356
     success:^(OpenStackRequest *request) {
357
         [activityIndicatorView stopAnimatingAndRemoveFromSuperview];
358
         container.metadata = [NSMutableDictionary dictionary];
359
         for (NSString *header in request.responseHeaders) {
360
             NSString *metadataKey;
361
             NSString *metadataValue;
362
             if ([header rangeOfString:@"X-Container-Meta-"].location != NSNotFound) {
363
                 metadataKey = [NSString decodeFromPercentEscape:[header substringFromIndex:17]];
364
                 metadataValue = [NSString decodeFromPercentEscape:[request.responseHeaders objectForKey:header]];
365
                 [container.metadata setObject:metadataValue forKey:metadataKey];
366
             }
367
         } 
368
         [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:kMetadata] withRowAnimation:UITableViewRowAnimationFade];
369
     }
370
     failure:^(OpenStackRequest *request) {
371
         [activityIndicatorView stopAnimatingAndRemoveFromSuperview];
372
         [self alert:@"There was a problem retrieving the container's metadata." request:request]; 
373
     }];
374
}
375

    
376
@end
377