2 // RootViewController.m
5 // Created by Mike Mayo on 9/30/10.
6 // The OpenStack project is provided under the Apache 2.0 license.
9 #import "RootViewController.h"
10 #import "ProvidersViewController.h"
11 #import "OpenStackAccount.h"
14 #import "ActivityIndicatorView.h"
15 #import "UIViewController+Conveniences.h"
16 #import "SettingsViewController.h"
18 #import "PasscodeViewController.h"
19 #import "OpenStackAppDelegate.h"
20 #import "AccountHomeViewController.h"
21 #import "PithosImageViewController.h"
24 @implementation RootViewController
26 @synthesize tableView, popoverController, detailItem;
27 @synthesize restoreAccountView;
29 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
30 return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait);
33 - (void)restoreProviderView:(AccountDetailsViewController *)accountDetailsViewController {
34 OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate];
35 ProvidersViewController *vc = [[ProvidersViewController alloc] initWithNibName:@"ProvidersViewController" bundle:nil];
36 vc.rootViewController = self;
37 if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
38 vc.modalPresentationStyle = UIModalPresentationFormSheet;
39 if (app.rootViewController.popoverController != nil) {
40 [app.rootViewController.popoverController dismissPopoverAnimated:YES];
43 [self presentModalViewControllerWithNavigation:vc animated:NO];
44 [vc restoreAccountDetailsViewController:accountDetailsViewController];
48 - (void)restoreAccountView:(AccountSettingsViewController *)accountSettingsViewController {
49 /*NSArray *pathList = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
50 NSString *path = [pathList objectAtIndex:0];
51 NSString *filePath = [NSString stringWithFormat:@"%@/iostestfile.txt", path];
53 /* self.navigationItem.title = @"Accounts";
55 self.navigationItem.leftBarButtonItem = self.editButtonItem;
57 UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addButtonPressed:)];
58 self.navigationItem.rightBarButtonItem = addButton;
61 AccountHomeViewController *vc = [[AccountHomeViewController alloc] initWithNibName:@"AccountHomeViewController" bundle:nil];
62 vc.account = accountSettingsViewController.account;
63 vc.account.hasBeenRefreshed = NO;
64 vc.rootViewController = self;
65 [self.navigationController pushViewController:vc animated:YES];
70 #pragma mark Split view support
73 When setting the detail item, update the view and dismiss the popover controller if it's showing.
75 - (void)setDetailItem:(id)newDetailItem {
76 if (detailItem != newDetailItem) {
78 detailItem = [newDetailItem retain];
81 if (self.popoverController != nil) {
82 [self.popoverController dismissPopoverAnimated:YES];
86 - (void)splitViewController:(UISplitViewController*)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem*)barButtonItem forPopoverController: (UIPopoverController*)pc {
87 OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate];
88 app.barButtonItem = barButtonItem;
89 UIViewController *vc = [[[app.splitViewController.viewControllers objectAtIndex:1] viewControllers] lastObject];
90 barButtonItem.title = [[[self.navigationController.viewControllers lastObject] navigationItem] title];
91 vc.navigationItem.leftBarButtonItem = barButtonItem;
92 self.popoverController = pc;
95 - (void)splitViewController: (UISplitViewController*)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem {
96 OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate];
97 app.barButtonItem = barButtonItem;
98 UIViewController *vc = [[[app.splitViewController.viewControllers objectAtIndex:1] viewControllers] lastObject];
99 vc.navigationItem.leftBarButtonItem = nil;
100 self.popoverController = nil;
104 #pragma mark Button Handlers
106 - (void)addButtonPressed:(id)sender {
107 OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate];
108 ProvidersViewController *vc = [[ProvidersViewController alloc] initWithNibName:@"ProvidersViewController" bundle:nil];
109 vc.rootViewController = self;
110 if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
111 vc.modalPresentationStyle = UIModalPresentationFormSheet;
112 if (app.rootViewController.popoverController != nil) {
113 [app.rootViewController.popoverController dismissPopoverAnimated:YES];
116 [self presentModalViewControllerWithNavigation:vc];
120 - (void)settingsButtonPressed:(id)sender {
122 //self.navigationController.navigationBarHidden = YES;
124 //UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 460.0)];
126 SettingsViewController *settingsViewController = [[SettingsViewController alloc] initWithNibName:@"SettingsViewController" bundle:nil];
128 UINavigationController *settingsNavigationController = [[UINavigationController alloc] initWithRootViewController:settingsViewController];
129 settingsNavigationController.view.frame = CGRectMake(0.0, 0.0, 320.0, 460.0);
131 if (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad) {
132 settingsNavigationController.navigationBar.tintColor = self.navigationController.navigationBar.tintColor;
133 settingsNavigationController.navigationBar.translucent = self.navigationController.navigationBar.translucent;
134 settingsNavigationController.navigationBar.opaque = self.navigationController.navigationBar.opaque;
135 settingsNavigationController.navigationBar.barStyle = self.navigationController.navigationBar.barStyle;
137 settingsNavigationController.navigationBar.barStyle = UIBarStyleBlack;
138 settingsNavigationController.navigationBar.opaque = NO;
141 if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
142 if (self.popoverController != nil) {
143 [self.popoverController dismissPopoverAnimated:YES];
145 settingsNavigationController.modalPresentationStyle = UIModalPresentationFormSheet;
146 [self presentModalViewController:settingsNavigationController animated:YES];
148 settingsNavigationController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
149 [self presentModalViewController:settingsNavigationController animated:YES];
152 [settingsViewController release];
153 [settingsNavigationController release];
159 #pragma mark View lifecycle
161 - (void)setEditing:(BOOL)editing animated:(BOOL)animated {
162 [self.tableView setEditing:editing animated:animated];
163 [super setEditing:editing animated:animated];
166 - (void)presentAndRelease:(NSTimer *)timer {
167 UIViewController *vc = [timer.userInfo objectForKey:@"vc"];
168 [self presentModalViewControllerWithNavigation:vc animated:NO];
172 - (void)viewDidLoad {
175 self.navigationItem.title = @"Accounts";
177 self.navigationItem.leftBarButtonItem = self.editButtonItem;
179 UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addButtonPressed:)];
180 self.navigationItem.rightBarButtonItem = addButton;
184 - (void)viewWillAppear:(BOOL)animated {
185 [super viewWillAppear:animated];
186 [self.tableView reloadData];
188 if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
189 PithosImageViewController *vc = [[PithosImageViewController alloc] initWithNibName:@"PithosImageViewController" bundle:nil];
190 [self.navigationController presentPrimaryViewController:vc];
196 - (void)viewDidAppear:(BOOL)animated {
197 [super viewDidAppear:animated];
199 if (!viewHasAppearedBefore) {
200 if ([[OpenStackAccount accounts] count] == 0) {
201 // if there are no accounts, go straight to the add account screen on launch
202 ProvidersViewController *vc = [[ProvidersViewController alloc] initWithNibName:@"ProvidersViewController" bundle:nil];
203 vc.rootViewController = self;
204 if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
205 vc.modalPresentationStyle = UIModalPresentationFormSheet;
207 [self presentModalViewControllerWithNavigation:vc];
209 } else if (([[OpenStackAccount accounts] count] == 1) && (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad)) {
210 // if there's only one account, go to its home screen
211 // NOTE: not doing this on iPad because it screws up the split view controller.
212 // TODO: make this work well with split view on iPad
213 AccountHomeViewController *vc = [[AccountHomeViewController alloc] initWithNibName:@"AccountHomeViewController" bundle:nil];
214 vc.account = [[OpenStackAccount accounts] objectAtIndex:0];
215 vc.rootViewController = self;
216 vc.rootViewIndexPath = [NSIndexPath indexPathForRow:0 inSection:0];
217 [self.navigationController pushViewController:vc animated:NO];
220 viewHasAppearedBefore = YES;
225 - (void)viewWillDisappear:(BOOL)animated {
226 [super viewWillDisappear:animated];
230 - (void)viewDidDisappear:(BOOL)animated {
231 [super viewDidDisappear:animated];
236 #pragma mark Table view data source
238 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
242 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
243 return [[OpenStackAccount accounts] count];
246 - (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
248 static NSString *CellIdentifier = @"Cell";
250 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
252 cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
253 cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
256 // Configure the cell.
257 OpenStackAccount *account = [[OpenStackAccount accounts] objectAtIndex:indexPath.row];
258 cell.textLabel.text = account.username;
259 cell.detailTextLabel.text = account.provider.name;
261 if (account.provider.logoURLs && [account.provider.logoURLs objectForKey:@"provider_icon"]) {
262 cell.imageView.image = [UIImage imageNamed:[account.provider.logoURLs objectForKey:@"provider_icon"]];
264 cell.imageView.image = [UIImage imageNamed:@"pithos-solo-smallest.png"];
270 - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
274 - (void)tableView:(UITableView *)aTableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
276 if (editingStyle == UITableViewCellEditingStyleDelete) {
277 NSMutableArray *accounts = [NSMutableArray arrayWithArray:[OpenStackAccount accounts]];
278 [[accounts objectAtIndex:indexPath.row] setFlaggedForDelete:YES];
279 [accounts removeObjectAtIndex:indexPath.row];
280 [OpenStackAccount persist:accounts];
282 // Delete the row from the data source.
283 [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
285 } else if (editingStyle == UITableViewCellEditingStyleInsert) {
286 // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
290 // Override to support rearranging the table view.
291 - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
292 NSMutableArray *accounts = [NSMutableArray arrayWithArray:[OpenStackAccount accounts]];
293 OpenStackAccount *account = [accounts objectAtIndex:fromIndexPath.row];
294 [accounts removeObjectAtIndex:fromIndexPath.row];
295 [accounts insertObject:account atIndex:toIndexPath.row];
296 [OpenStackAccount persist:accounts];
299 // Override to support conditional rearranging of the table view.
300 - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
301 // Return NO if you do not want the item to be re-orderable.
306 #pragma mark Table view delegate
308 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
309 AccountHomeViewController *vc = [[AccountHomeViewController alloc] initWithNibName:@"AccountHomeViewController" bundle:nil];
310 vc.account = [[OpenStackAccount accounts] objectAtIndex:indexPath.row];
311 vc.account.hasBeenRefreshed = NO;
312 vc.rootViewController = self;
313 vc.rootViewIndexPath = indexPath;
314 [self.navigationController pushViewController:vc animated:YES];
319 #pragma mark Memory management
321 - (void)didReceiveMemoryWarning {
322 // Releases the view if it doesn't have a superview.
323 [super didReceiveMemoryWarning];
325 // Relinquish ownership any cached data, images, etc that aren't in use.
328 - (void)viewDidUnload {
329 // Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
330 // For example: self.myOutlet = nil;
336 [popoverController release];
337 [detailItem release];