2 // ContainersViewController.m
5 // Created by Mike Mayo on 12/7/10.
6 // The OpenStack project is provided under the Apache 2.0 license.
9 #import "NSObject+Conveniences.h"
10 #import "ContainersViewController.h"
11 #import "OpenStackAccount.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"
22 #import "AccountHomeViewController.h"
23 #import "ActivityIndicatorView.h"
25 @implementation ContainersViewController
27 @synthesize tableView, account, accountUsageInfo, accountHomeViewController, containerDetailViewController;
29 #pragma mark - View lifecycle
33 self.navigationItem.title = @"Containers";
38 - (void)viewWillAppear:(BOOL)animated {
39 [super viewWillAppear:animated];
41 if ([self.account.containers count] == 0) {
42 self.tableView.allowsSelection = NO;
43 self.tableView.scrollEnabled = NO;
44 [self.tableView reloadData];
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];
58 [self refreshButtonPressed:nil];
61 #pragma mark - Memory management
66 [containerDetailViewController release];
70 #pragma mark - Internal
72 - (void)createContainerWithName:(NSString *)containerName {
73 __block ActivityIndicatorView *activityIndicatorView = [ActivityIndicatorView activityIndicatorViewWithText:@"Creating container..."
74 andAddToView:self.view];
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];
83 failure:^(OpenStackRequest *request) {
84 [activityIndicatorView removeFromSuperview];
85 [self alert:@"There was a problem creating your container." request:request];
90 #pragma mark - Properties
92 - (NSString *)accountUsageInfo {
93 if (self.account.sharingAccount)
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]];
108 #pragma mark - Button Handlers
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];
118 [self presentModalViewControllerWithNavigation:vc];
122 - (IBAction)homeButtonPressed:(id)sender {
123 [self.navigationController popToViewController:accountHomeViewController animated:YES];
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);
139 [self.account persist];
140 containersLoaded = YES;
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"];
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];
161 #pragma mark - UITableViewDataSource
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;
168 self.tableView.allowsSelection = YES;
169 self.tableView.scrollEnabled = YES;
171 if (!containersLoaded && [self.account.containers count] == 0) {
174 return MAX(1, [account.containers count]);
178 - (CGFloat)tableView:(UITableView *)aTableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
179 if ([account.containers count] == 0) {
180 return aTableView.frame.size.height;
182 return aTableView.rowHeight;
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;
192 return [self tableView:tableView
193 emptyCellWithImage:[UIImage imageNamed:@"empty-containers.png"]
194 title:noContainersTitle
195 subtitle:noContainersSubtitle];
197 static NSString *CellIdentifier = @"Cell";
199 UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier];
201 cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
202 if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
203 cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
205 cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
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"];
215 cell.imageView.image = [UIImage imageNamed:@"ContainerIcon.png"];
217 if (!self.account.sharingAccount)
218 cell.detailTextLabel.text = [container osxStyleHumanizedSize];
224 #pragma mark - UITableViewDelegate
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];
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;
241 [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
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;
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];
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];