// // ContainersViewController.m // OpenStack // // Created by Mike Mayo on 12/7/10. // The OpenStack project is provided under the Apache 2.0 license. // #import "NSObject+Conveniences.h" #import "ContainersViewController.h" #import "OpenStackAccount.h" #import "Container.h" #import "AddContainerViewController.h" #import "UIViewController+Conveniences.h" #import "FolderViewController.h" #import "ContainerDetailViewController.h" #import "AccountManager.h" #import "OpenStackAppDelegate.h" #import "RootViewController.h" #import "APICallback.h" #import "GetCDNContainersRequest.h" #import "Provider.h" #import "AccountHomeViewController.h" @implementation ContainersViewController @synthesize tableView, account, accountUsageInfo, accountHomeViewController, containerDetailViewController; - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation { return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait); } #pragma mark - #pragma mark View lifecycle - (void)viewDidLoad { [super viewDidLoad]; self.navigationItem.title = @"Containers"; [self addAddButton]; [self addHomeButton]; if (!account.shared && !account.sharingAccount && containersLoaded) { if (![self.account.containers objectForKey:@"pithos"]) [self createContainerWithName:@"pithos"]; if (![self.account.containers objectForKey:@"trash"]) [self createContainerWithName:@"trash"]; } } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; if ([self.account.containers count] == 0) { self.tableView.allowsSelection = NO; self.tableView.scrollEnabled = NO; [self.tableView reloadData]; } if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { if ([self.account.containers count] == 0 ) { NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; [self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone]; [self tableView:self.tableView didSelectRowAtIndexPath:indexPath]; } else if ([self.tableView indexPathForSelectedRow].row == 0 && [self.tableView indexPathForSelectedRow].section == 0) { ContainerDetailViewController *vc = [[ContainerDetailViewController alloc] initWithNibName:@"ContainerDetailViewController" bundle:nil]; [self presentPrimaryViewController:vc]; [vc release]; } } if (!containersLoaded && [self.account.containers count] == 0) { [self refreshButtonPressed:nil]; } } - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; } #pragma mark - #pragma mark Button Handlers - (void)addButtonPressed:(id)sender { AddContainerViewController *vc = [[AddContainerViewController alloc] initWithNibName:@"AddContainerViewController" bundle:nil]; vc.containersViewController = self; vc.account = account; if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { vc.modalPresentationStyle = UIModalPresentationFormSheet; OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate]; if (app.rootViewController.popoverController != nil) { [app.rootViewController.popoverController dismissPopoverAnimated:YES]; } } [self presentModalViewControllerWithNavigation:vc]; [vc release]; } - (IBAction)homeButtonPressed:(id)sender { [self.navigationController popToViewController:accountHomeViewController animated:YES]; } - (void)enableRefreshButton { refreshButton.enabled = YES; [self hideToolbarActivityMessage]; if (!account.sharingAccount) [self showToolbarInfoMessage:accountUsageInfo]; } - (void)refreshButtonPressed:(id)sender { refreshButton.enabled = NO; //BOOL hadZeroContainers = [self.account.containers count] == 0; if (!account.sharingAccount) [self hideToolbarInfoMessage]; [self showToolbarActivityMessage:@"Refreshing containers..."]; [[self.account.manager getContainers] success:^(OpenStackRequest *request) { self.account.containers = [request containers]; self.account.containerCount = [self.account.containers count]; self.account.totalBytesUsed = [[request.responseHeaders objectForKey:@"X-Account-Bytes-Used"] longLongValue]; self.account.quota = [[request.responseHeaders objectForKey:@"X-Account-Policy-Quota"] longLongValue]; self.accountUsageInfo = [NSString stringWithFormat:@"%@ used, %@ available", [NSObject osxStyleHumanizedBytes:self.account.totalBytesUsed], [NSObject osxStyleHumanizedBytes:self.account.quota]]; [self.account persist]; containersLoaded = YES; [self enableRefreshButton]; [self.tableView reloadData]; //GetCDNContainersRequest *cdnRequest = [GetCDNContainersRequest request:self.account]; //[cdnRequest startAsynchronous]; } failure:^(OpenStackRequest *request) { containersLoaded = NO; [self enableRefreshButton]; if (request.responseStatusCode != 0) { [self alert:@"There was a problem loading your containers." request:request]; } }]; } #pragma mark - #pragma mark Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if ([self.account.containers count] == 0) { self.tableView.allowsSelection = NO; self.tableView.scrollEnabled = NO; } else { self.tableView.allowsSelection = YES; self.tableView.scrollEnabled = YES; } if (!containersLoaded && [self.account.containers count] == 0) { return 0; } else { return MAX(1, [account.containers count]); } } - (CGFloat)tableView:(UITableView *)aTableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if ([account.containers count] == 0) { return aTableView.frame.size.height; } else { return aTableView.rowHeight; } } - (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { if (containersLoaded && [self.account.containers count] == 0) { NSString *noContainersTitle = self.account.shared ? @"No shared containers" : @"No containers"; NSString *noContainersSubtitle = self.account.shared ? @"" : @"Tap the + button to create a new container"; self.navigationItem.rightBarButtonItem.enabled = !self.account.shared; return [self tableView:tableView emptyCellWithImage: [UIImage imageNamed:@"empty-containers.png"] title:noContainersTitle subtitle:noContainersSubtitle]; } else { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease]; if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; } else { cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton; } } Container *container = [self.account.pithosSortedContainers objectAtIndex:indexPath.row]; cell.textLabel.text = container.name; if ([container.name isEqualToString:@"pithos"]) cell.imageView.image = [UIImage imageNamed:@"PithosContainerIcon.png"]; else if ([container.name isEqualToString:@"trash"]) cell.imageView.image = [UIImage imageNamed:@"TrashIcon.png"]; else cell.imageView.image = [UIImage imageNamed:@"ContainerIcon.png"]; if (!self.account.sharingAccount) cell.detailTextLabel.text = [container osxStyleHumanizedSize]; return cell; } } #pragma mark - #pragma mark Table view delegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { Container *container = nil; if ([account.containers count] > 0) { container = [self.account.pithosSortedContainers objectAtIndex:indexPath.row]; FolderViewController *vc = [[FolderViewController alloc] initWithNibName:@"FolderViewController" bundle:nil]; vc.account = self.account; vc.container = container; vc.folder = container.rootFolder; vc.containersViewController = self; vc.selectedContainerIndexPath = indexPath; [self.navigationController pushViewController:vc animated:YES]; [vc release]; [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; } if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { ContainerDetailViewController *vc = [[ContainerDetailViewController alloc] initWithNibName:@"ContainerDetailViewController" bundle:nil]; vc.account = self.account; vc.container = container; vc.containersViewController = self; vc.selectedContainerIndexPath = indexPath; [self presentPrimaryViewController:vc]; self.containerDetailViewController = vc; [vc release]; } } - (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath { Container *container = nil; if ([account.containers count] > 0) { container = [self.account.pithosSortedContainers objectAtIndex:indexPath.row]; } ContainerDetailViewController *vc = [[ContainerDetailViewController alloc] initWithNibName:@"ContainerDetailViewController" bundle:nil]; vc.account = self.account; vc.container = container; vc.containersViewController = self; vc.selectedContainerIndexPath = indexPath; [self.navigationController pushViewController:vc animated:YES]; [vc release]; } #pragma mark - #pragma mark Helper methods - (NSString *)humanReadableSize:(unsigned long long)bytes { NSString *sizeUnit = @"bytes"; double sizeInBytes = bytes; if (bytes > 1023 && bytes < 1048576) { sizeInBytes = bytes / 1024.0; sizeUnit = @"Kb"; } else if (bytes > 1048575 && bytes < 1073741824) { sizeInBytes = bytes / 1048576.0; sizeUnit = @"Mb"; } else if (bytes > 1073741823) { sizeInBytes = bytes / 1073741824.0; sizeUnit = @"Gb"; } NSString *humanReadableString = [NSString stringWithFormat:@"%.1f %@", sizeInBytes, sizeUnit]; humanReadableString = [humanReadableString stringByReplacingOccurrencesOfString:@".0" withString:@""]; return humanReadableString; } - (void)createContainerWithName:(NSString *)containerName { [self hideToolbarInfoMessage]; [self showToolbarActivityMessage:@"Creating container..."]; Container *container = [[Container alloc] init]; container.name = containerName; [[self.account.manager createContainer:container] success:^(OpenStackRequest *request) { [self hideToolbarActivityMessage]; if (!account.sharingAccount) [self showToolbarInfoMessage:accountUsageInfo]; [self.tableView reloadData]; } failure:^(OpenStackRequest *request) { [self hideToolbarActivityMessage]; if (!account.sharingAccount) [self showToolbarInfoMessage:accountUsageInfo]; [self alert:@"There was a problem creating your container." request:request]; }]; [container release]; } #pragma mark - #pragma mark Memory management - (void)dealloc { [accountUsageInfo release]; [tableView release]; [account release]; [containerDetailViewController release]; [super dealloc]; } @end