// // FolderDetailViewController.m // pithos-ios // // Copyright 2011 GRNET S.A. All rights reserved. // // Redistribution and use in source and binary forms, with or // without modification, are permitted provided that the following // conditions are met: // // 1. Redistributions of source code must retain the above // copyright notice, this list of conditions and the following // disclaimer. // // 2. Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following // disclaimer in the documentation and/or other materials // provided with the distribution. // // THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS // OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF // USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED // AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. // // The views and conclusions contained in the software and // documentation are those of the authors and should not be // interpreted as representing official policies, either expressed // or implied, of GRNET S.A. #import "FolderDetailViewController.h" #import "EditMetadataViewController.h" #import "EditPermissionsViewController.h" #import "StorageObject.h" #import "APICallback.h" #import "AccountManager.h" #import "UIViewController+Conveniences.h" #import "NSString+Conveniences.h" #define kOverview 0 #define kMetadata 1 #define kPermissions 2 #define maxMetadataViewableLength 12 @implementation FolderDetailViewController @synthesize account, container, folder, folderViewController; #pragma mark - #pragma mark Memory management - (void)dealloc { [object release]; [account release]; [container release]; [folderViewController release]; [folder release]; [permissions release]; [super dealloc]; } - (void)didReceiveMemoryWarning { // Releases the view if it doesn't have a superview. [super didReceiveMemoryWarning]; // Release any cached data, images, etc that aren't in use. } #pragma mark - View lifecycle - (void)viewDidLoad { [super viewDidLoad]; permissions = [[NSMutableDictionary alloc] init]; if (folder.sharing.length > 0) { NSArray *sharingArray = [folder.sharing componentsSeparatedByString:@";"]; for (NSString *typeSpecificPermissions in sharingArray) { NSArray *array=[typeSpecificPermissions componentsSeparatedByString:@"="]; NSString *permissionsType = [array objectAtIndex:0]; if ([permissionsType hasPrefix:@" "]) permissionsType = [permissionsType substringFromIndex:1]; NSArray *users = [[array objectAtIndex:1] componentsSeparatedByString:@","]; for (NSString *user in users) { [permissions setObject:permissionsType forKey:user]; } } } folderIsReadOnly = NO; if (account.sharingAccount) { if ([permissions count] > 0) { folderIsReadOnly = [[permissions objectForKey:[account username]] isEqualToString:@"read"]; } } object = [[StorageObject alloc] init]; object.name = folder.name; object.metadata = folder.metadata; object.fullPath = [folder fullPath]; object.sharing = folder.sharing; object.contentType = folder.contentType; } - (void)viewDidUnload { [super viewDidUnload]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self.tableView reloadData]; } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; if (folder.metadata == nil) { [self reloadMetadataSection]; } } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; folder.sharing = object.sharing; } - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation { return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait); } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 3; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (section == kOverview) return 2; else if (section == kPermissions) { if (account.sharingAccount) return [permissions count]; else return 1 + [permissions count]; } else if (section == kMetadata) if (folderIsReadOnly) return [folder.metadata count]; else return 1 + [folder.metadata count]; return 0; } - (CGFloat)findLabelHeight:(NSString*)text font:(UIFont *)font { CGSize textLabelSize; if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { textLabelSize = CGSizeMake(537.0, 9000.0f); } else { textLabelSize = CGSizeMake(221.0, 9000.0f); } CGSize stringSize = [text sizeWithFont:font constrainedToSize:textLabelSize lineBreakMode:UILineBreakModeCharacterWrap]; return stringSize.height; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { CGFloat result; if (indexPath.section == kOverview) { if (indexPath.row == 0) { result = 22 + [self findLabelHeight:folder.name font:[UIFont systemFontOfSize:18.0]]; return MAX(tableView.rowHeight, result); } else if (indexPath.row == 1) { NSString *folderFullPathToShow = folder.fullPath; if ([folderFullPathToShow hasPrefix:@"/"]) { folderFullPathToShow = [folderFullPathToShow substringFromIndex:1]; } result = 22 + [self findLabelHeight:folderFullPathToShow font:[UIFont systemFontOfSize:18.0]]; return MAX(tableView.rowHeight, result); } } return tableView.rowHeight; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease]; cell.textLabel.backgroundColor = [UIColor clearColor]; cell.detailTextLabel.backgroundColor = [UIColor clearColor]; cell.detailTextLabel.numberOfLines = 0; cell.detailTextLabel.lineBreakMode = UILineBreakModeWordWrap; cell.detailTextLabel.textAlignment = UITextAlignmentRight; } if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { cell.backgroundColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:0.8]; } if (indexPath.section == kOverview) { cell.accessoryType = UITableViewCellAccessoryNone; cell.selectionStyle = UITableViewCellSelectionStyleNone; cell.accessoryView = nil; if (indexPath.row == 0) { cell.textLabel.text = @"Name"; cell.detailTextLabel.text = folder.name; } else if (indexPath.row == 1) { cell.textLabel.text = @"Full Path"; NSString *folderFullPathToShow = folder.fullPath; if ([folderFullPathToShow hasPrefix:@"/"]) { folderFullPathToShow = [folderFullPathToShow substringFromIndex:1]; } cell.detailTextLabel.text = folderFullPathToShow; } } else if (indexPath.section == kMetadata) { if (folderIsReadOnly) { cell.accessoryType = UITableViewCellAccessoryNone; cell.selectionStyle = UITableViewCellSelectionStyleNone; cell.userInteractionEnabled = NO; } else { cell.selectionStyle = UITableViewCellSelectionStyleBlue; cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; } cell.accessoryView = nil; if (indexPath.row == [folder.metadata count]) { cell.textLabel.text = @"Add Metadata"; cell.detailTextLabel.text = @""; } else { NSString *key = [[folder.metadata allKeys] objectAtIndex:indexPath.row]; NSString *value = [folder.metadata objectForKey:key]; NSString *metadataKeyCellText = key; NSString *metadataValueCellText = value; if ([metadataKeyCellText length] > maxMetadataViewableLength) { metadataKeyCellText = [metadataKeyCellText substringToIndex:(maxMetadataViewableLength - 3)]; metadataKeyCellText = [metadataKeyCellText stringByAppendingString:@"..."]; } if ([metadataValueCellText length] > maxMetadataViewableLength) { metadataValueCellText = [metadataValueCellText substringToIndex:(maxMetadataViewableLength - 3)]; metadataValueCellText = [metadataValueCellText stringByAppendingString:@"..."]; } cell.textLabel.text = metadataKeyCellText; cell.detailTextLabel.text = metadataValueCellText; } } else if (indexPath.section == kPermissions) { if (account.sharingAccount) { cell.accessoryType = UITableViewCellAccessoryNone; cell.selectionStyle = UITableViewCellSelectionStyleNone; cell.userInteractionEnabled = NO; } else { cell.selectionStyle = UITableViewCellSelectionStyleBlue; cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; } cell.accessoryView = nil; if (indexPath.row == [permissions count]) { cell.textLabel.text = @"Add Permissions"; cell.detailTextLabel.text = @""; } else { NSString *user = [[permissions allKeys] objectAtIndex:indexPath.row]; cell.textLabel.text = user; cell.detailTextLabel.text = [permissions objectForKey:user]; } } return cell; } #pragma mark - Table view delegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.section == kMetadata) { EditMetadataViewController *vc = [[EditMetadataViewController alloc] initWithNibName:@"EditMetadataViewController" bundle:nil]; NSString *metadataKey; NSString *metadataValue; if (indexPath.row == [self.folder.metadata count]) { metadataKey = @""; metadataValue = @""; vc.removeMetadataEnabled = FALSE; vc.navigationItem.title = @"Add Metadata"; } else { metadataKey = [[self.folder.metadata allKeys] objectAtIndex:indexPath.row]; metadataValue = [self.folder.metadata objectForKey:metadataKey]; vc.removeMetadataEnabled = TRUE; vc.navigationItem.title = @"Edit Metadata"; } vc.metadataKey = metadataKey; vc.metadataValue = metadataValue; vc.account = account; vc.container = container; vc.object = object; vc.objectIsFolder = YES; vc.folderViewController = folderViewController; [self.navigationController pushViewController:vc animated:YES]; [vc release]; } else if (indexPath.section == kPermissions) { EditPermissionsViewController *vc = [[EditPermissionsViewController alloc] initWithNibName:@"EditPermissionsViewController" bundle:nil]; NSString *user; if (indexPath.row == [permissions count]) { user = @""; vc.removePermissionsEnabled = NO; vc.navigationItem.title = @"Add Permissions"; } else { user = [[permissions allKeys] objectAtIndex:indexPath.row]; NSString *userPermissions = [permissions objectForKey:user]; if ([userPermissions rangeOfString:@"read"].location != NSNotFound) vc.readPermissionSelected = YES; else vc.readPermissionSelected = NO; if ([userPermissions rangeOfString:@"write"].location != NSNotFound) vc.writePermissionSelected = YES; else vc.writePermissionSelected = NO; vc.removePermissionsEnabled = YES; vc.navigationItem.title = @"Edit Permissions"; } vc.user = user; vc.permissions = permissions; vc.account = account; vc.container = container; vc.object = object; vc.objectIsFolder = YES; vc.folderViewController = folderViewController; [self.navigationController pushViewController:vc animated:YES]; [vc release]; } } #pragma mark - #pragma mark Helper functions - (void)reloadMetadataSection { NSString *activityMessage = @"Loading metadata..."; ActivityIndicatorView *activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage]; [activityIndicatorView addToView:self.view]; [[self.account.manager getObjectInfo:container object:object version:nil] success:^(OpenStackRequest *request) { [activityIndicatorView removeFromSuperviewAndRelease]; folder.metadata = [NSMutableDictionary dictionary]; for (NSString *header in request.responseHeaders) { NSString *metadataKey; NSString *metadataValue; if ([header rangeOfString:@"X-Object-Meta-"].location != NSNotFound) { metadataKey = [NSString decodeFromPercentEscape:[header substringFromIndex:14]]; metadataValue = [NSString decodeFromPercentEscape:[request.responseHeaders objectForKey:header]]; [folder.metadata setObject:metadataValue forKey:metadataKey]; } } object.metadata = folder.metadata; NSIndexSet *metadataSections = [NSIndexSet indexSetWithIndex:kMetadata]; [self.tableView reloadSections:metadataSections withRowAnimation:UITableViewRowAnimationFade]; } failure:^(OpenStackRequest *request) { [activityIndicatorView removeFromSuperviewAndRelease]; [self alert:@"There was a problem retrieving the object's metadata." request:request]; }]; } @end