Merge branch 'master' of https://code.grnet.gr/git/pithos-ios
[pithos-ios] / Classes / ContainersViewController.m
1 //
2 //  ContainersViewController.m
3 //  OpenStack
4 //
5 //  Created by Mike Mayo on 12/7/10.
6 //  The OpenStack project is provided under the Apache 2.0 license.
7 //
8
9 #import "NSObject+Conveniences.h"
10 #import "ContainersViewController.h"
11 #import "OpenStackAccount.h"
12 #import "Container.h"
13 #import "AddContainerViewController.h"
14 #import "UIViewController+Conveniences.h"
15 #import "FolderViewController.h"
16 #import "ContainerDetailViewController.h"
17 #import "AccountManager.h"
18 #import "OpenStackAppDelegate.h"
19 #import "RootViewController.h"
20 #import "APICallback.h"
21 #import "Provider.h"
22 #import "AccountHomeViewController.h"
23 #import "ActivityIndicatorView.h"
24
25 @implementation ContainersViewController
26
27 @synthesize tableView, account, accountUsageInfo, accountHomeViewController, containerDetailViewController;
28
29 #pragma mark - View lifecycle
30
31 - (void)viewDidLoad {
32     [super viewDidLoad];
33     self.navigationItem.title = @"Containers";
34     [self addAddButton]; 
35     [self addHomeButton];
36 }
37
38 - (void)viewWillAppear:(BOOL)animated {
39     [super viewWillAppear:animated];
40         
41     if ([self.account.containers count] == 0) {
42         self.tableView.allowsSelection = NO;
43         self.tableView.scrollEnabled = NO;
44         [self.tableView reloadData];        
45     }   
46     if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
47         if ([self.account.containers count] == 0 ) {
48             NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
49             [self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
50             [self tableView:self.tableView didSelectRowAtIndexPath:indexPath];
51         } else if ([self.tableView indexPathForSelectedRow].row == 0 && [self.tableView indexPathForSelectedRow].section == 0) {
52             ContainerDetailViewController *vc = [[ContainerDetailViewController alloc] initWithNibName:@"ContainerDetailViewController" bundle:nil];
53             [self presentPrimaryViewController:vc];
54             [vc release]; 
55         }
56     }
57     
58     [self refreshButtonPressed:nil];
59 }
60
61 #pragma mark - Memory management
62
63 - (void)dealloc {
64     [tableView release];
65     [account release];
66     [containerDetailViewController release];
67     [super dealloc];
68 }
69
70 #pragma mark - Internal
71
72 - (void)createContainerWithName:(NSString *)containerName {
73     __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Creating container..."
74                                                                                                    andAddToView:self.view];
75
76     Container *container = [[Container alloc] init];
77     container.name = containerName;
78     [[self.account.manager createContainer:container]
79      success:^(OpenStackRequest *request) {
80          [activityIndicatorView removeFromSuperview];
81          [self.tableView reloadData];
82      }
83      failure:^(OpenStackRequest *request) {
84          [activityIndicatorView removeFromSuperview];
85          [self alert:@"There was a problem creating your container." request:request];
86      }];
87     [container release];
88 }
89
90 #pragma mark - Properties
91
92 - (NSString *)accountUsageInfo {
93     if (self.account.sharingAccount)
94         return nil;
95     if (self.account.bytesUsed && self.account.policyQuota) {
96         return [NSString stringWithFormat:@"%@ used, %@ available",
97                 [NSObject osxStyleHumanizedBytesNumber:self.account.bytesUsed],
98                 [NSObject osxStyleHumanizedBytesNumber:self.account.policyQuota]];
99     } else if (self.account.bytesUsed) {
100         return [NSString stringWithFormat:@"%@ used", [NSObject osxStyleHumanizedBytesNumber:self.account.bytesUsed]];
101     } else if (self.account.policyQuota) {
102         return [NSString stringWithFormat:@"%@ available", [NSObject osxStyleHumanizedBytesNumber:self.account.policyQuota]];
103     } else {
104         return nil;
105     }
106 }
107
108 #pragma mark - Button Handlers
109
110 - (void)addButtonPressed:(id)sender {
111     AddContainerViewController *vc = [[AddContainerViewController alloc] initWithNibName:@"AddContainerViewController" bundle:nil];
112     vc.containersViewController = self;
113     vc.account = account;
114     if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
115         OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate];
116         [app.rootViewController.popoverController dismissPopoverAnimated:YES];
117     }
118     [self presentModalViewControllerWithNavigation:vc];
119     [vc release];
120 }
121
122 - (IBAction)homeButtonPressed:(id)sender {
123     [self.navigationController popToViewController:accountHomeViewController animated:YES];
124 }
125
126 - (void)refreshButtonPressed:(id)sender {
127     __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Loading..."
128                                                                                                    andAddToView:self.view];
129     [[self.account.manager getContainers] success:^(OpenStackRequest *request) {
130         self.account.containers = [request containers];
131         self.account.containerCount = [self.account.containers count];
132         NSString *bytesUsedString = [request.responseHeaders objectForKey:@"X-Account-Bytes-Used"];
133         self.account.bytesUsed = (bytesUsedString ?
134                                   [NSNumber numberWithUnsignedLongLong:strtoull([bytesUsedString UTF8String], NULL, 0)] : nil);
135         NSString *policyQuotaString = [request.responseHeaders objectForKey:@"X-Account-Policy-Quota"];
136         self.account.policyQuota = (policyQuotaString ?
137                                     [NSNumber numberWithUnsignedLongLong:strtoull([policyQuotaString UTF8String], NULL, 0)] : nil);
138         
139         [self.account persist];
140         containersLoaded = YES;
141         
142         [activityIndicatorView removeFromSuperview];
143         [self showToolbarInfoMessage:self.accountUsageInfo];
144         [self.tableView reloadData];
145         if (!account.shared && !account.sharingAccount) {
146             if (![self.account.containers objectForKey:@"pithos"])
147                 [self createContainerWithName:@"pithos"];
148             if (![self.account.containers objectForKey:@"trash"])
149                 [self createContainerWithName:@"trash"];
150         }
151     } failure:^(OpenStackRequest *request) {
152         containersLoaded = NO;
153         [activityIndicatorView removeFromSuperview];
154         [self showToolbarInfoMessage:self.accountUsageInfo];
155         if (request.responseStatusCode != 0) {
156             [self alert:@"There was a problem loading containers." request:request addAccountSettingsButton:YES];
157         }
158     }];
159 }
160
161 #pragma mark - UITableViewDataSource
162
163 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
164     if ([self.account.containers count] == 0) {
165         self.tableView.allowsSelection = NO;
166         self.tableView.scrollEnabled = NO;
167     } else {
168         self.tableView.allowsSelection = YES;
169         self.tableView.scrollEnabled = YES;
170     }
171     if (!containersLoaded && [self.account.containers count] == 0) {
172         return 0;
173     } else {
174         return MAX(1, [account.containers count]);    
175     }
176 }
177
178 - (CGFloat)tableView:(UITableView *)aTableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
179     if ([account.containers count] == 0) {
180         return aTableView.frame.size.height;
181     } else {
182         return aTableView.rowHeight;
183     }
184 }
185
186 - (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
187     if (containersLoaded && [self.account.containers count] == 0) {
188         NSString *noContainersTitle = self.account.shared ? @"No shared containers" : @"No containers";
189         NSString *noContainersSubtitle = self.account.shared ? @"" : @"Tap the + button to create a new container";
190         self.navigationItem.rightBarButtonItem.enabled = !self.account.shared;
191         
192         return [self tableView:tableView
193             emptyCellWithImage:[UIImage imageNamed:@"empty-containers.png"]
194                          title:noContainersTitle
195                       subtitle:noContainersSubtitle];
196     } else {   
197         static NSString *CellIdentifier = @"Cell";
198         
199         UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier];
200         if (cell == nil) {
201             cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
202             if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
203                 cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
204             } else {
205                 cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
206             }
207         }
208         Container *container = [self.account.pithosSortedContainers objectAtIndex:indexPath.row];
209         cell.textLabel.text = container.name;
210         if ([container.name isEqualToString:@"pithos"])
211             cell.imageView.image = [UIImage imageNamed:@"PithosContainerIcon.png"];
212         else if ([container.name isEqualToString:@"trash"])
213             cell.imageView.image = [UIImage imageNamed:@"TrashIcon.png"];
214         else
215             cell.imageView.image = [UIImage imageNamed:@"ContainerIcon.png"];
216                                     
217         if (!self.account.sharingAccount)
218             cell.detailTextLabel.text = [container osxStyleHumanizedSize];
219         
220         return cell;
221     }
222 }
223
224 #pragma mark - UITableViewDelegate
225
226 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
227     Container *container = nil;
228     if ([account.containers count] > 0) {
229         container = [self.account.pithosSortedContainers objectAtIndex:indexPath.row];
230
231         FolderViewController *vc = (([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) ?
232                                     [[FolderViewController alloc] initWithNibName:@"FolderViewController-iPad" bundle:nil] :
233                                     [[FolderViewController alloc] initWithNibName:@"FolderViewController" bundle:nil]);
234         vc.account = self.account;
235         vc.container = container;
236         vc.containersViewController = self;
237         vc.selectedContainerIndexPath = indexPath;
238         [self.navigationController pushViewController:vc animated:YES];
239         vc.folder = container.rootFolder;
240         [vc release];
241         [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
242     }
243     
244     if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
245         ContainerDetailViewController *vc = [[ContainerDetailViewController alloc] initWithNibName:@"ContainerDetailViewController" bundle:nil];
246         vc.account = self.account;
247         vc.container = container;
248         vc.containersViewController = self;
249         vc.selectedContainerIndexPath = indexPath;
250         [self presentPrimaryViewController:vc];
251         self.containerDetailViewController = vc;
252         [vc release];
253     }
254 }
255
256 - (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath {
257     Container *container = nil;
258     if ([account.containers count] > 0) {
259         container = [self.account.pithosSortedContainers objectAtIndex:indexPath.row];
260     }
261     ContainerDetailViewController *vc = [[ContainerDetailViewController alloc] initWithNibName:@"ContainerDetailViewController" bundle:nil];
262     vc.account = self.account;
263     vc.container = container;
264     vc.containersViewController = self;
265     vc.selectedContainerIndexPath = indexPath;
266     [self.navigationController pushViewController:vc animated:YES];
267     [vc release];
268 }
269
270 @end