Expanded open file functionality to use available apps.
[pithos-ios] / Classes / RootViewController.m
1 //
2 //  RootViewController.m
3 //  OpenStack
4 //
5 //  Created by Mike Mayo on 9/30/10.
6 //  The OpenStack project is provided under the Apache 2.0 license.
7 //
8
9 #import "RootViewController.h"
10 #import "ProvidersViewController.h"
11 #import "OpenStackAccount.h"
12 #import "Provider.h"
13 #import "Archiver.h"
14 #import "ActivityIndicatorView.h"
15 #import "UIViewController+Conveniences.h"
16 #import "SettingsViewController.h"
17 #import "Keychain.h"
18 #import "PasscodeViewController.h"
19 #import "OpenStackAppDelegate.h"
20 #import "AccountHomeViewController.h"
21
22
23 @implementation RootViewController
24
25 @synthesize tableView, popoverController, detailItem;
26 @synthesize restoreAccountView;
27
28 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
29     return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait);
30 }
31
32 - (void)restoreProviderView:(AccountDetailsViewController *)accountDetailsViewController {
33     OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate];
34     ProvidersViewController *vc = [[ProvidersViewController alloc] initWithNibName:@"ProvidersViewController" bundle:nil];
35     vc.rootViewController = self;
36     if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
37         vc.modalPresentationStyle = UIModalPresentationFormSheet;
38         if (app.rootViewController.popoverController != nil) {
39             [app.rootViewController.popoverController dismissPopoverAnimated:YES];
40         }
41     }   
42     [self presentModalViewControllerWithNavigation:vc animated:NO];
43     [vc restoreAccountDetailsViewController:accountDetailsViewController];
44     [vc release];    
45 }
46
47 - (void)restoreAccountView:(AccountSettingsViewController *)accountSettingsViewController {
48     AccountHomeViewController *vc = [[AccountHomeViewController alloc] initWithNibName:@"AccountHomeViewController" bundle:nil];
49     vc.account = accountSettingsViewController.account;
50     vc.account.hasBeenRefreshed = NO;
51     vc.rootViewController = self;
52     [self.navigationController pushViewController:vc animated:YES];
53     [vc release];
54 }
55
56 #pragma mark -
57 #pragma mark Split view support
58
59 /*
60  When setting the detail item, update the view and dismiss the popover controller if it's showing.
61  */
62 - (void)setDetailItem:(id)newDetailItem {
63     if (detailItem != newDetailItem) {
64         [detailItem release];
65         detailItem = [newDetailItem retain];
66     }
67     
68     if (self.popoverController != nil) {
69         [self.popoverController dismissPopoverAnimated:YES];
70     }
71 }
72
73 - (void)splitViewController:(UISplitViewController*)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem*)barButtonItem forPopoverController: (UIPopoverController*)pc {
74     OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate];
75     app.barButtonItem = barButtonItem;
76     UIViewController *vc = [[[app.splitViewController.viewControllers objectAtIndex:1] viewControllers] lastObject];
77     barButtonItem.title = [[[self.navigationController.viewControllers lastObject] navigationItem] title];
78     vc.navigationItem.leftBarButtonItem = barButtonItem;
79     self.popoverController = pc;
80 }
81
82 - (void)splitViewController: (UISplitViewController*)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem {    
83     OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate];
84     app.barButtonItem = barButtonItem;
85     UIViewController *vc = [[[app.splitViewController.viewControllers objectAtIndex:1] viewControllers] lastObject];
86     vc.navigationItem.leftBarButtonItem = nil;
87     self.popoverController = nil;
88 }
89
90 #pragma mark -
91 #pragma mark Button Handlers
92
93 - (void)addButtonPressed:(id)sender {
94     OpenStackAppDelegate *app = [[UIApplication sharedApplication] delegate];
95     ProvidersViewController *vc = [[ProvidersViewController alloc] initWithNibName:@"ProvidersViewController" bundle:nil];
96     vc.rootViewController = self;
97     if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
98         vc.modalPresentationStyle = UIModalPresentationFormSheet;
99         if (app.rootViewController.popoverController != nil) {
100             [app.rootViewController.popoverController dismissPopoverAnimated:YES];
101         }
102     }                
103     [self presentModalViewControllerWithNavigation:vc];
104     [vc release];    
105 }
106    
107 - (void)settingsButtonPressed:(id)sender {
108
109     //self.navigationController.navigationBarHidden = YES;
110     
111     //UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 460.0)];
112
113     SettingsViewController *settingsViewController = [[SettingsViewController alloc] initWithNibName:@"SettingsViewController" bundle:nil];
114     
115     UINavigationController *settingsNavigationController = [[UINavigationController alloc] initWithRootViewController:settingsViewController];
116     settingsNavigationController.view.frame = CGRectMake(0.0, 0.0, 320.0, 460.0);
117     
118     if (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad) {
119         settingsNavigationController.navigationBar.tintColor = self.navigationController.navigationBar.tintColor;
120         settingsNavigationController.navigationBar.translucent = self.navigationController.navigationBar.translucent;
121         settingsNavigationController.navigationBar.opaque = self.navigationController.navigationBar.opaque;
122         settingsNavigationController.navigationBar.barStyle = self.navigationController.navigationBar.barStyle;
123     } else {
124         settingsNavigationController.navigationBar.barStyle = UIBarStyleBlack;
125         settingsNavigationController.navigationBar.opaque = NO;
126     }
127
128     if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
129         if (self.popoverController != nil) {
130             [self.popoverController dismissPopoverAnimated:YES];
131         }        
132         settingsNavigationController.modalPresentationStyle = UIModalPresentationFormSheet;
133         [self presentModalViewController:settingsNavigationController animated:YES];
134     } else {
135         settingsNavigationController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
136         [self presentModalViewController:settingsNavigationController animated:YES];
137     }
138     
139     [settingsViewController release];
140     [settingsNavigationController release];
141     
142     
143 }
144
145 #pragma mark -
146 #pragma mark View lifecycle
147
148 - (void)setEditing:(BOOL)editing animated:(BOOL)animated {
149     [self.tableView setEditing:editing animated:animated];
150     [super setEditing:editing animated:animated];
151 }
152
153 - (void)presentAndRelease:(NSTimer *)timer {
154     UIViewController *vc = [timer.userInfo objectForKey:@"vc"];
155     [self presentModalViewControllerWithNavigation:vc animated:NO];
156     [vc release];
157 }
158
159 - (void)viewDidLoad {
160     [super viewDidLoad];
161     self.navigationItem.title = @"Accounts";
162
163     self.navigationItem.leftBarButtonItem = self.editButtonItem;
164     
165     UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addButtonPressed:)];
166     self.navigationItem.rightBarButtonItem = addButton;
167     [addButton release];
168     
169     if ([[OpenStackAccount accounts] count] == 0) {
170         // if there are no accounts, go straight to the add account screen on launch
171         ProvidersViewController *vc = [[ProvidersViewController alloc] initWithNibName:@"ProvidersViewController" bundle:nil];
172         vc.rootViewController = self;
173         if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
174             vc.modalPresentationStyle = UIModalPresentationFormSheet;
175         }                
176         [self presentModalViewControllerWithNavigation:vc animated:NO];
177         [vc release];
178
179     } else if ([[OpenStackAccount accounts] count] == 1 && UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad) {
180         // if there's only one account, go to its home screen
181         // NOTE: not doing this on iPad because it screws up the split view controller.
182         // TODO: make this work well with split view on iPad
183         AccountHomeViewController *vc = [[AccountHomeViewController alloc] initWithNibName:@"AccountHomeViewController" bundle:nil];
184         vc.account = [[OpenStackAccount accounts] objectAtIndex:0];
185         vc.rootViewController = self;
186         vc.rootViewIndexPath = [NSIndexPath indexPathForRow:0 inSection:0];
187         [self.navigationController pushViewController:vc animated:NO];
188         [vc release];
189     }
190
191 }
192
193 - (void)viewWillAppear:(BOOL)animated {
194     [super viewWillAppear:animated];
195     [self.tableView reloadData];    
196 }
197
198 - (void)viewDidAppear:(BOOL)animated {
199     [super viewDidAppear:animated];
200 }
201
202 /*
203 - (void)viewWillDisappear:(BOOL)animated {
204         [super viewWillDisappear:animated];
205 }
206 */
207 /*
208 - (void)viewDidDisappear:(BOOL)animated {
209         [super viewDidDisappear:animated];
210 }
211 */
212
213 #pragma mark -
214 #pragma mark Table view data source
215
216 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
217     return 1;
218 }
219
220 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
221     return [[OpenStackAccount accounts] count];
222 }
223
224 - (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
225     
226     static NSString *CellIdentifier = @"Cell";
227     
228     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
229     if (cell == nil) {
230         cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
231         cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
232     }
233     
234         // Configure the cell.
235     OpenStackAccount *account = [[OpenStackAccount accounts] objectAtIndex:indexPath.row];
236     cell.textLabel.text = account.username;
237     cell.detailTextLabel.text = account.provider.name;
238         
239     if (account.provider.logoURLs && [account.provider.logoURLs objectForKey:@"provider_icon"]) {
240         cell.imageView.image = [UIImage imageNamed:[account.provider.logoURLs objectForKey:@"provider_icon"]];
241     } else {
242         cell.imageView.image = [UIImage imageNamed:@"pithos-solo-smallest.png"];
243     }
244
245     return cell;
246 }
247
248 - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
249     return YES;
250 }
251
252 - (void)tableView:(UITableView *)aTableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
253     
254     if (editingStyle == UITableViewCellEditingStyleDelete) {
255         NSMutableArray *accounts = [NSMutableArray arrayWithArray:[OpenStackAccount accounts]];
256         [[accounts objectAtIndex:indexPath.row] setFlaggedForDelete:YES];
257         [accounts removeObjectAtIndex:indexPath.row];
258         [OpenStackAccount persist:accounts];
259
260         // Delete the row from the data source.
261         [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
262
263     } else if (editingStyle == UITableViewCellEditingStyleInsert) {
264         // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
265     }   
266 }
267
268 // Override to support rearranging the table view.
269 - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
270     NSMutableArray *accounts = [NSMutableArray arrayWithArray:[OpenStackAccount accounts]];
271     OpenStackAccount *account = [accounts objectAtIndex:fromIndexPath.row];
272     [accounts removeObjectAtIndex:fromIndexPath.row];
273     [accounts insertObject:account atIndex:toIndexPath.row];
274     [OpenStackAccount persist:accounts];
275 }
276
277 // Override to support conditional rearranging of the table view.
278 - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
279     // Return NO if you do not want the item to be re-orderable.
280     return YES;
281 }
282
283 #pragma mark -
284 #pragma mark Table view delegate
285
286 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
287     AccountHomeViewController *vc = [[AccountHomeViewController alloc] initWithNibName:@"AccountHomeViewController" bundle:nil];
288     vc.account = [[OpenStackAccount accounts] objectAtIndex:indexPath.row];
289     vc.account.hasBeenRefreshed = NO;
290     vc.rootViewController = self;
291     vc.rootViewIndexPath = indexPath;
292     [self.navigationController pushViewController:vc animated:YES];
293     [vc release];
294 }
295
296 #pragma mark -
297 #pragma mark Memory management
298
299 - (void)didReceiveMemoryWarning {
300     // Releases the view if it doesn't have a superview.
301     [super didReceiveMemoryWarning];
302     
303     // Relinquish ownership any cached data, images, etc that aren't in use.
304 }
305
306 - (void)viewDidUnload {
307     // Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
308     // For example: self.myOutlet = nil;
309 }
310
311
312 - (void)dealloc {
313     [tableView release];
314     [popoverController release];
315     [detailItem release];     
316     [super dealloc];
317 }
318
319
320 @end
321