- (void)writeObjectMetadataSucceeded:(OpenStackRequest *)request {
if ([request isSuccess]) {
+ NSNotification *notification = [NSNotification notificationWithName:@"writeObjectMetadataSucceeded" object:[request.userInfo objectForKey:@"object"] userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
+ [[NSNotificationCenter defaultCenter] postNotification:notification];
} else {
- NSNotification *notification = [NSNotification notificationWithName:@"getObjectsFailed" object:self.account userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
+ NSNotification *notification = [NSNotification notificationWithName:@"writeObjectMetadataFailed" object:[request.userInfo objectForKey:@"object"] userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
[[NSNotificationCenter defaultCenter] postNotification:notification];
}
}
- (void)writeObjectMetadataFailed:(OpenStackRequest *)request {
- NSNotification *notification = [NSNotification notificationWithName:@"writeObjectMetadataFailed" object:self.account userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
+ NSNotification *notification = [NSNotification notificationWithName:@"writeObjectMetadataFailed" object:[request.userInfo objectForKey:@"object"] userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
[[NSNotificationCenter defaultCenter] postNotification:notification];
}
NSString *name;
NSUInteger count;
unsigned long long bytes;
+
+ // metadata
+ NSMutableDictionary *metadata;
// TODO: wade having trouble with directories without markers: user_files/12345/wade.jpg
@property (nonatomic, retain) NSString *name;
@property (nonatomic, assign) NSUInteger count;
@property (nonatomic, assign) unsigned long long bytes;
+@property (nonatomic, retain) NSMutableDictionary *metadata;
-(NSString *)humanizedSize;
// regular container attributes
@synthesize name, count, bytes;
+@synthesize metadata;
// CDN container attributes
@synthesize cdnEnabled, ttl, cdnURL, logRetention, referrerACL, useragentACL, rootFolder;
// regular attributes
container.name = [dict objectForKey:@"name"];
+ // metadata
+ container.metadata = [NSMutableDictionary dictionary];
+ for (NSString *key in dict) {
+ if ([key hasPrefix:@"x_container_meta_"]) {
+ NSString *metadataKey = [key substringFromIndex:17];
+ [container.metadata setObject:[dict objectForKey:key] forKey:metadataKey];
+ }
+ }
+
// if count is in here, we're parsing from the object storage API
if ([dict objectForKey:@"count"]) {
container.count = [[dict objectForKey:@"count"] intValue];
#import "ReferrerACLViewController.h"
#import "UserAgentACLViewController.h"
#import "ContainersViewController.h"
+#import "EditMetadataViewController.h"
#import "Folder.h"
#define kOverview 0
-#define kCDNAccess 1
-#define kCDNAttributes 2
-#define kLogRetention 3
-#define kReferrerACL 4
-#define kUserAgentACL 5
-
-/*
- #define kOverview 0
- #define kCDNAccess 1
- #define kCDNAttributes 2
- #define kLogRetention 3
- #define kReferrerACL 4
- #define kUserAgentACL 5
+#define kMetadata 1
+#define kCDNAccess 2
+#define kCDNAttributes 3
+#define kLogRetention 4
+#define kReferrerACL 5
+#define kUserAgentACL 6
+
+#define maxMetadataViewableLength 12
+
+
+/*
Name
Size
cdnURLActionSheet = [[UIActionSheet alloc] initWithTitle:container.cdnURL delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Copy to Pasteboard", nil];
deleteActionSheet = [[UIActionSheet alloc] initWithTitle:@"Are you sure you want to delete this container? This operation cannot be undone." delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:@"Delete Container" otherButtonTitles:nil];
- deleteSection = container.cdnEnabled ? 6 : 2;
+ deleteSection = container.cdnEnabled ? 7 : 2;
}
- (void)viewWillAppear:(BOOL)animated {
}
originalTTL = container.ttl;
[self setBackgroundView];
+ [self.tableView reloadData];
}
#pragma mark -
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if (self.container) {
if (transitioning) {
- return container.cdnEnabled ? 3 : 7;
+ return container.cdnEnabled ? 3 : 8;
} else {
- return container.cdnEnabled ? 7 : 3;
+ return container.cdnEnabled ? 8 : 3;
}
} else {
return 0;
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
- if (section == deleteSection) {
- return 1;
- } else if (section == kOverview) {
- return 2;
- } else if (section == kCDNAccess) {
- return 1;
- } else if (section == kCDNAttributes) {
+ if (section == kOverview) {
return 2;
+ } else if (section == kMetadata) {
+ return 1 + [container.metadata count];
} else {
return 1;
}
cell.textLabel.text = @"Size";
cell.detailTextLabel.text = [container humanizedSize];
}
- } else if (indexPath.section == kCDNAccess) {
- cell.textLabel.text = @"Publish to CDN";
- cell.detailTextLabel.text = @"";
- cell.accessoryView = cdnEnabledSwitch;
- cell.selectionStyle = UITableViewCellSelectionStyleNone;
- } else if (indexPath.section == deleteSection) {
- return [self tableView:tableView deleteCellForRowAtIndexPath:indexPath];
- } else if (indexPath.section == kCDNAttributes) {
- if (indexPath.row == 0) {
- cell.textLabel.text = @"Public URL";
- //cell.detailTextLabel.text = container.cdnURL;
+ } else if (indexPath.section == kMetadata) {
+ cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
+ cell.selectionStyle = UITableViewCellSelectionStyleBlue;
+ cell.accessoryView = nil;
+ if (indexPath.row == [container.metadata count]) {
+ cell.textLabel.text = @"Add Metadata";
cell.detailTextLabel.text = @"";
- cell.accessoryView = nil;
- cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
- cell.selectionStyle = UITableViewCellSelectionStyleBlue;
- cell.detailTextLabel.lineBreakMode = UILineBreakModeTailTruncation;
- cell.detailTextLabel.numberOfLines = 0;
- //cell.detailTextLabel.adjustsFontSizeToFitWidth = YES;
- } else if (indexPath.row == 1) {
- return [self tableView:tableView ttlCellForRowAtIndexPath:indexPath];
+ } else {
+ NSString *key = [[container.metadata allKeys] objectAtIndex:indexPath.row];
+ NSString *value = [container.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 == deleteSection) {
+ return [self tableView:tableView deleteCellForRowAtIndexPath:indexPath];
} else if (indexPath.section == kLogRetention) {
cell.textLabel.text = @"Log Retention";
cell.detailTextLabel.text = @"";
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
- if (indexPath.section == deleteSection) {
+
+ if (indexPath.section == kMetadata) {
+ EditMetadataViewController *vc = [[EditMetadataViewController alloc] initWithNibName:@"EditMetadataViewController" bundle:nil];
+ NSString *metadataKey;
+ NSString *metadataValue;
+
+ if (indexPath.row == [self.container.metadata count]) {
+ metadataKey = @"";
+ metadataValue = @"";
+ vc.deleteEnabled = FALSE;
+ vc.navigationItem.title = @"Add Metadata";
+ }
+ else {
+ metadataKey = [[self.container.metadata allKeys] objectAtIndex:indexPath.row];
+ metadataValue = [self.container.metadata objectForKey:metadataKey];
+ vc.deleteEnabled = TRUE;
+ vc.navigationItem.title = @"Edit Metadata";
+ }
+
+ StorageObject *object = [[[StorageObject alloc] init] autorelease];
+ object.name = container.name;
+ object.metadata = container.metadata;
+ object.fullPath = @"";
+
+ vc.metadataKey = metadataKey;
+ vc.metadataValue = metadataValue;
+ vc.account = account;
+ vc.container = container;
+ vc.object = object;
+
+ [self.navigationController pushViewController:vc animated:YES];
+ [vc release];
+ } else if (indexPath.section == deleteSection) {
if (self.container.count == 0 || ([self.container.rootFolder.folders count] + [self.container.rootFolder.objects count] == 0)) {
[deleteActionSheet showInView:self.view];
}
--- /dev/null
+//
+// EditMetadataViewController.h
+// 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 <UIKit/UIKit.h>
+#import "OpenStackViewController.h"
+#import "OpenStackAccount.h"
+#import "Container.h"
+#import "Folder.h"
+#import "StorageObject.h"
+#import "ActivityIndicatorView.h"
+
+
+@interface EditMetadataViewController : UITableViewController <UITextFieldDelegate> {
+
+ OpenStackAccount *account;
+ Container *container;
+ StorageObject *object;
+
+ NSString *metadataKey;
+ NSString *metadataValue;
+
+ ActivityIndicatorView *activityIndicatorView;
+ id successObserver;
+ id failureObserver;
+
+ BOOL deleteEnabled;
+}
+
+@property (nonatomic, retain) OpenStackAccount *account;
+@property (nonatomic, retain) Container *container;
+@property (nonatomic, retain) StorageObject *object;
+
+@property (nonatomic, retain) NSString *metadataKey;
+@property (nonatomic, retain) NSString *metadataValue;
+
+@property (nonatomic) BOOL deleteEnabled;
+
+
+@end
--- /dev/null
+//
+// EditMetadataViewController.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 "EditMetadataViewController.h"
+#import "AccountManager.h"
+#import "UIViewController+Conveniences.h"
+
+
+
+@implementation EditMetadataViewController
+
+
+@synthesize container, account, object;
+
+@synthesize metadataKey;
+@synthesize metadataValue;
+@synthesize deleteEnabled;
+
+#define kMetadata 0
+#define kSaveMedata 1
+#define kDeleteMetadata 2
+
+
+- (void)dealloc
+{
+ [account release];
+ [container release];
+ [object release];
+ [metadataKey release];
+ [metadataValue 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];
+}
+
+- (void)viewDidUnload
+{
+ [super viewDidUnload];
+}
+
+- (void)viewWillAppear:(BOOL)animated
+{
+ [super viewWillAppear:animated];
+}
+
+- (void)viewDidAppear:(BOOL)animated
+{
+ [super viewDidAppear:animated];
+}
+
+- (void)viewWillDisappear:(BOOL)animated
+{
+ [super viewWillDisappear:animated];
+}
+
+- (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 (deleteEnabled)? 3:2;
+}
+
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
+{
+ if (section == kMetadata)
+ return 2;
+ else
+ return 1;
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ static NSString *CellIdentifier = @"Cell";
+ UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
+ if (cell == nil) {
+ cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
+ }
+ CGRect bounds = [cell.contentView bounds];
+ CGRect rect = CGRectInset(bounds, 20.0, 10.0);
+ UITextField *textField = [[UITextField alloc] initWithFrame:rect];
+ [textField setFrame:rect];
+ [textField setClearButtonMode:UITextFieldViewModeWhileEditing];
+ [textField setBackgroundColor:[UIColor whiteColor]];
+ [textField setOpaque:YES];
+ [textField setAutocorrectionType:UITextAutocorrectionTypeNo];
+ [textField setAutocapitalizationType:UITextAutocapitalizationTypeNone];
+ [textField setDelegate:self];
+
+ if (indexPath.section == kMetadata) {
+ if (indexPath.row == 0) {
+ [textField setReturnKeyType:UIReturnKeyNext];
+ textField.placeholder = @"Key";
+ textField.text = metadataKey;
+ textField.tag = 0;
+ }
+ else if (indexPath.row == 1) {
+ textField.placeholder = @"Value";
+ textField.text = metadataValue;
+ textField.tag = 1;
+ }
+
+ cell.selectionStyle = UITableViewCellSelectionStyleNone;
+ [cell.contentView addSubview:textField];
+ }
+ else if (indexPath.section == kSaveMedata)
+ cell.textLabel.text = @"Save";
+ else if (indexPath.section == kDeleteMetadata)
+ cell.textLabel.text = @"Delete";
+
+ return cell;
+}
+
+
+#pragma mark - Table view delegate
+
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
+{
+ NSString *activityMessage;
+ NSIndexPath *keyCellIndexPath;
+ NSIndexPath *valueCellIndexPath;
+ UITableViewCell *cell;
+ switch (indexPath.section) {
+ case kSaveMedata:
+ keyCellIndexPath = [NSIndexPath indexPathForRow:0 inSection:kMetadata];
+ cell = [self.tableView cellForRowAtIndexPath:keyCellIndexPath];
+ UITextField *textField = [[cell.contentView subviews] objectAtIndex:0];
+ NSString *newMetadataKey = textField.text;
+
+ if ([newMetadataKey length] == 0
+ || [[newMetadataKey stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0) {
+ [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
+ [self alert:@"Invalid input" message:@"Metadata key cannot be empty"];
+ return;
+ }
+
+ valueCellIndexPath = [NSIndexPath indexPathForRow:1 inSection:kMetadata];
+ cell = [self.tableView cellForRowAtIndexPath:valueCellIndexPath];
+ textField = [[cell.contentView subviews] objectAtIndex:0];
+ NSString *newMetadataValue = textField.text;
+
+ activityMessage = @"Saving metadata";
+
+ activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage];
+ [activityIndicatorView addToView:self.view];
+
+ [object.metadata removeObjectForKey:metadataKey];
+ [object.metadata setObject:newMetadataValue forKey:newMetadataKey];
+ [self.account.manager writeObjectMetadata:container object:object];
+ successObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"writeObjectMetadataSucceeded"
+ object:object
+ queue:[NSOperationQueue mainQueue]
+ usingBlock:^(NSNotification *notification)
+ {
+ self.metadataKey = newMetadataKey;
+ self.metadataValue = newMetadataValue;
+
+ [activityIndicatorView removeFromSuperviewAndRelease];
+ [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
+ [[NSNotificationCenter defaultCenter] removeObserver:successObserver];
+ }];
+
+ failureObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"writeObjectMetadataFailed"
+ object:object
+ queue:[NSOperationQueue mainQueue]
+ usingBlock:^(NSNotification *notification)
+ {
+ [object.metadata removeObjectForKey:newMetadataKey];
+ [object.metadata setObject:metadataValue forKey:metadataKey];
+ [activityIndicatorView removeFromSuperviewAndRelease];
+ [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
+ [self alert:@"There was a problem saving the metadata." request:[notification.userInfo objectForKey:@"request"]];
+
+ [[NSNotificationCenter defaultCenter] removeObserver:failureObserver];
+ }];
+
+ break;
+ case kDeleteMetadata:
+ activityMessage = @"Deleting metadata";
+ activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage];
+ [activityIndicatorView addToView:self.view];
+
+ [object.metadata removeObjectForKey:metadataKey];
+ [self.account.manager writeObjectMetadata:container object:object];
+ successObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"writeObjectMetadataSucceeded"
+ object:object
+ queue:[NSOperationQueue mainQueue]
+ usingBlock:^(NSNotification *notification)
+ {
+ [activityIndicatorView removeFromSuperviewAndRelease];
+ [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
+ self.metadataKey = @"";
+ self.metadataValue = @"";
+
+ [self.tableView reloadData];
+ [[NSNotificationCenter defaultCenter] removeObserver:successObserver];
+ }];
+
+ failureObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"writeObjectMetadataFailed"
+ object:object
+ queue:[NSOperationQueue mainQueue]
+ usingBlock:^(NSNotification *notification)
+ {
+ [object.metadata setObject:metadataValue forKey:metadataKey];
+ [activityIndicatorView removeFromSuperviewAndRelease];
+ [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
+ [self alert:@"There was a problem saving the metadata." request:[notification.userInfo objectForKey:@"request"]];
+
+ [[NSNotificationCenter defaultCenter] removeObserver:failureObserver];
+ }];
+
+ break;
+ }
+}
+
+#pragma mark - Textfield delegate
+
+- (void)textFieldDidEndEditing:(UITextField *)textField
+{
+ if ([textField tag] == 0) {
+ if ([textField.text length] == 0
+ || [[textField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0) {
+ [self alert:@"Invalid input" message:@"Metadata key cannot be empty"];
+ }
+ }
+}
+
+
+
+- (BOOL)textFieldShouldReturn:(UITextField *)textField
+{
+
+ if ([textField returnKeyType] == UIReturnKeyNext)
+ {
+ NSInteger nextTag = [textField tag] + 1;
+ UIView *nextTextField = [self.tableView viewWithTag:nextTag];
+ [nextTextField becomeFirstResponder];
+ }
+ else
+ {
+ [textField resignFirstResponder];
+ }
+
+ return YES;
+}
+
+@end
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.10">
+ <data>
+ <int key="IBDocument.SystemTarget">1056</int>
+ <string key="IBDocument.SystemVersion">10K549</string>
+ <string key="IBDocument.InterfaceBuilderVersion">1306</string>
+ <string key="IBDocument.AppKitVersion">1038.36</string>
+ <string key="IBDocument.HIToolboxVersion">461.00</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string key="NS.object.0">301</string>
+ </object>
+ <object class="NSArray" key="IBDocument.IntegratedClassDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>IBProxyObject</string>
+ <string>IBUITableView</string>
+ </object>
+ <object class="NSArray" key="IBDocument.PluginDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.Metadata">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys" id="0">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <reference key="dict.values" ref="0"/>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBProxyObject" id="372490531">
+ <string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
+ <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+ </object>
+ <object class="IBProxyObject" id="975951072">
+ <string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
+ <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+ </object>
+ <object class="IBUITableView" id="403916641">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">274</int>
+ <string key="NSFrameSize">{292, 440}</string>
+ <reference key="NSSuperview"/>
+ <reference key="NSWindow"/>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">10</int>
+ <object class="NSImage" key="NSImage">
+ <int key="NSImageFlags">549453824</int>
+ <string key="NSSize">{84, 1}</string>
+ <object class="NSMutableArray" key="NSReps">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <integer value="0"/>
+ <object class="NSBitmapImageRep">
+ <object class="NSData" key="NSTIFFRepresentation">
+ <bytes key="NS.bytes">TU0AKgAAAVjFzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/
+y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/
+xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/
+xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/
+xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/
+xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P8ADQEAAAMAAAABAFQAAAEB
+AAMAAAABAAEAAAECAAMAAAAEAAAB+gEDAAMAAAABAAEAAAEGAAMAAAABAAIAAAERAAQAAAABAAAACAES
+AAMAAAABAAEAAAEVAAMAAAABAAQAAAEWAAMAAAABAAEAAAEXAAQAAAABAAABUAEcAAMAAAABAAEAAAFS
+AAMAAAABAAEAAAFTAAMAAAAEAAACAgAAAAAACAAIAAgACAABAAEAAQABA</bytes>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="NSColor" key="NSColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MCAwAA</bytes>
+ </object>
+ </object>
+ <string key="IBUIColorCocoaTouchKeyPath">groupTableViewBackgroundColor</string>
+ </object>
+ <bool key="IBUIClipsSubviews">YES</bool>
+ <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+ <bool key="IBUIBouncesZoom">NO</bool>
+ <int key="IBUIStyle">1</int>
+ <int key="IBUISeparatorStyle">1</int>
+ <int key="IBUISectionIndexMinimumDisplayRowCount">0</int>
+ <bool key="IBUIShowsSelectionImmediatelyOnTouchBegin">YES</bool>
+ <float key="IBUIRowHeight">44</float>
+ <float key="IBUISectionHeaderHeight">10</float>
+ <float key="IBUISectionFooterHeight">10</float>
+ </object>
+ </object>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <object class="NSMutableArray" key="connectionRecords">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">dataSource</string>
+ <reference key="source" ref="403916641"/>
+ <reference key="destination" ref="372490531"/>
+ </object>
+ <int key="connectionID">9</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">delegate</string>
+ <reference key="source" ref="403916641"/>
+ <reference key="destination" ref="372490531"/>
+ </object>
+ <int key="connectionID">10</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">view</string>
+ <reference key="source" ref="372490531"/>
+ <reference key="destination" ref="403916641"/>
+ </object>
+ <int key="connectionID">11</int>
+ </object>
+ </object>
+ <object class="IBMutableOrderedSet" key="objectRecords">
+ <object class="NSArray" key="orderedObjects">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBObjectRecord">
+ <int key="objectID">0</int>
+ <reference key="object" ref="0"/>
+ <reference key="children" ref="1000"/>
+ <nil key="parent"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-1</int>
+ <reference key="object" ref="372490531"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">File's Owner</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-2</int>
+ <reference key="object" ref="975951072"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">8</int>
+ <reference key="object" ref="403916641"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="flattenedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>-1.CustomClassName</string>
+ <string>-2.CustomClassName</string>
+ <string>8.IBPluginDependency</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>EditMetadataViewController</string>
+ <string>UIResponder</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="unlocalizedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <reference key="dict.values" ref="0"/>
+ </object>
+ <nil key="activeLocalization"/>
+ <object class="NSMutableDictionary" key="localizations">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <reference key="dict.values" ref="0"/>
+ </object>
+ <nil key="sourceID"/>
+ <int key="maxID">13</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes">
+ <object class="NSMutableArray" key="referencedPartialClassDescriptions">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBPartialClassDescription">
+ <string key="className">EditMetadataViewController</string>
+ <string key="superclassName">UITableViewController</string>
+ <object class="NSMutableDictionary" key="outlets">
+ <string key="NS.key.0">aTableView</string>
+ <string key="NS.object.0">UITableView</string>
+ </object>
+ <object class="NSMutableDictionary" key="toOneOutletInfosByName">
+ <string key="NS.key.0">aTableView</string>
+ <object class="IBToOneOutletInfo" key="NS.object.0">
+ <string key="name">aTableView</string>
+ <string key="candidateClassName">UITableView</string>
+ </object>
+ </object>
+ <object class="IBClassDescriptionSource" key="sourceIdentifier">
+ <string key="majorKey">IBProjectSource</string>
+ <string key="minorKey">./Classes/EditMetadataViewController.h</string>
+ </object>
+ </object>
+ </object>
+ </object>
+ <int key="IBDocument.localizationMode">0</int>
+ <string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3</string>
+ <integer value="3000" key="NS.object.0"/>
+ </object>
+ <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+ <int key="IBDocument.defaultPropertyAccessControl">3</int>
+ <string key="IBCocoaTouchPluginVersion">301</string>
+ </data>
+</archive>
NSMutableDictionary *folders;
NSMutableDictionary *objects;
NSArray *sortedContents;
+
+ NSMutableDictionary *metadata;
}
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSMutableDictionary *folders;
@property (nonatomic, retain) NSMutableDictionary *objects;
@property (readonly, retain) NSArray *sortedContents;
+@property (nonatomic, retain) NSMutableDictionary *metadata;
+ (id)folder;
- (NSArray *)sortedContents;
@implementation Folder
-@synthesize name, parent, folders, objects;
+@synthesize name, parent, folders, objects, metadata;
+ (id)folder {
Folder *folder = [[[self alloc] init] autorelease];
Folder *folder = [[Folder alloc] init];
folder.name = object.name;
folder.parent = self;
+ folder.metadata = object.metadata;
[self.folders setObject:folder forKey:folder.name];
[folder release];
} else {
folder.name = folderName;
folder.parent = self;
folder.objects = files;
+ StorageObject *object = [objs objectForKey:folderName];
+ folder.metadata = object.metadata;
[self.folders setObject:folder forKey:folder.name];
[folder release];
}
--- /dev/null
+//
+// FolderDetailViewController.h
+// 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 <UIKit/UIKit.h>
+#import "OpenStackAccount.h"
+#import "Container.h"
+#import "Folder.h"
+
+
+
+@interface FolderDetailViewController : UITableViewController {
+ OpenStackAccount *account;
+ Container *container;
+ Folder *folder;
+}
+
+@property (nonatomic, retain) OpenStackAccount *account;
+@property (nonatomic, retain) Container *container;
+@property (nonatomic, retain) Folder *folder;
+
+@end
--- /dev/null
+//
+// 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"
+
+#define kOverview 0
+#define kMetadata 1
+
+#define maxMetadataViewableLength 12
+
+
+@implementation FolderDetailViewController
+
+@synthesize account, container, folder;
+
+- (id)initWithStyle:(UITableViewStyle)style
+{
+ self = [super initWithStyle:style];
+ if (self) {
+ // Custom initialization
+ }
+ return self;
+}
+
+- (void)dealloc
+{
+ [folder 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];
+}
+
+- (void)viewDidUnload
+{
+ [super viewDidUnload];
+}
+
+- (void)viewWillAppear:(BOOL)animated
+{
+ [super viewWillAppear:animated];
+
+ [self.tableView reloadData];
+}
+
+- (void)viewDidAppear:(BOOL)animated
+{
+ [super viewDidAppear:animated];
+}
+
+- (void)viewWillDisappear:(BOOL)animated
+{
+ [super viewWillDisappear:animated];
+}
+
+- (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 2;
+}
+
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
+{
+ if (section == kOverview)
+ return 2;
+ else
+ return 1 + [folder.metadata count];
+}
+
+- (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";
+ cell.detailTextLabel.text = [folder fullPath];
+ }
+ } else if (indexPath.section == kMetadata) {
+ cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
+ cell.selectionStyle = UITableViewCellSelectionStyleBlue;
+ 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;
+ }
+ }
+
+ 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.deleteEnabled = FALSE;
+ vc.navigationItem.title = @"Add Metadata";
+ }
+ else {
+ metadataKey = [[self.folder.metadata allKeys] objectAtIndex:indexPath.row];
+ metadataValue = [self.folder.metadata objectForKey:metadataKey];
+ vc.deleteEnabled = TRUE;
+ vc.navigationItem.title = @"Edit Metadata";
+ }
+
+ StorageObject *object = [[[StorageObject alloc] init] autorelease];
+ object.name = folder.name;
+ object.metadata = folder.metadata;
+ object.fullPath = [folder fullPath];
+
+ vc.metadataKey = metadataKey;
+ vc.metadataValue = metadataValue;
+ vc.account = account;
+ vc.container = container;
+ vc.object = object;
+
+ [self.navigationController pushViewController:vc animated:YES];
+ [vc release];
+ }
+}
+
+@end
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.10">
+ <data>
+ <int key="IBDocument.SystemTarget">1056</int>
+ <string key="IBDocument.SystemVersion">10K549</string>
+ <string key="IBDocument.InterfaceBuilderVersion">1306</string>
+ <string key="IBDocument.AppKitVersion">1038.36</string>
+ <string key="IBDocument.HIToolboxVersion">461.00</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ <string key="NS.object.0">301</string>
+ </object>
+ <object class="NSArray" key="IBDocument.IntegratedClassDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>IBProxyObject</string>
+ <string>IBUITableView</string>
+ </object>
+ <object class="NSArray" key="IBDocument.PluginDependencies">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ <object class="NSMutableDictionary" key="IBDocument.Metadata">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys" id="0">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ </object>
+ <reference key="dict.values" ref="0"/>
+ </object>
+ <object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBProxyObject" id="372490531">
+ <string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
+ <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+ </object>
+ <object class="IBProxyObject" id="975951072">
+ <string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
+ <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+ </object>
+ <object class="IBUITableView" id="873029372">
+ <reference key="NSNextResponder"/>
+ <int key="NSvFlags">274</int>
+ <string key="NSFrame">{{0, 20}, {320, 460}}</string>
+ <reference key="NSSuperview"/>
+ <reference key="NSNextKeyView"/>
+ <object class="NSColor" key="IBUIBackgroundColor">
+ <int key="NSColorSpace">10</int>
+ <object class="NSImage" key="NSImage">
+ <int key="NSImageFlags">549453824</int>
+ <string key="NSSize">{84, 1}</string>
+ <object class="NSMutableArray" key="NSReps">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <integer value="0"/>
+ <object class="NSBitmapImageRep">
+ <object class="NSData" key="NSTIFFRepresentation">
+ <bytes key="NS.bytes">TU0AKgAAAVjFzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/
+y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/
+xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/
+xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/
+xczU/8XM1P/FzNL/y9LY/8vS2P/FzNT/xczU/8XM1P/FzNT/xczS/8vS2P/L0tj/xczU/8XM1P/FzNT/
+xczU/8XM0v/L0tj/y9LY/8XM1P/FzNT/xczU/8XM1P/FzNL/y9LY/8vS2P8ADQEAAAMAAAABAFQAAAEB
+AAMAAAABAAEAAAECAAMAAAAEAAAB+gEDAAMAAAABAAEAAAEGAAMAAAABAAIAAAERAAQAAAABAAAACAES
+AAMAAAABAAEAAAEVAAMAAAABAAQAAAEWAAMAAAABAAEAAAEXAAQAAAABAAABUAEcAAMAAAABAAEAAAFS
+AAMAAAABAAEAAAFTAAMAAAAEAAACAgAAAAAACAAIAAgACAABAAEAAQABA</bytes>
+ </object>
+ </object>
+ </object>
+ </object>
+ <object class="NSColor" key="NSColor">
+ <int key="NSColorSpace">3</int>
+ <bytes key="NSWhite">MCAwAA</bytes>
+ </object>
+ </object>
+ <string key="IBUIColorCocoaTouchKeyPath">groupTableViewBackgroundColor</string>
+ </object>
+ <bool key="IBUIOpaque">NO</bool>
+ <bool key="IBUIClipsSubviews">YES</bool>
+ <bool key="IBUIClearsContextBeforeDrawing">NO</bool>
+ <object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics"/>
+ <string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
+ <bool key="IBUIBouncesZoom">NO</bool>
+ <int key="IBUIStyle">1</int>
+ <int key="IBUISeparatorStyle">1</int>
+ <int key="IBUISectionIndexMinimumDisplayRowCount">0</int>
+ <bool key="IBUIShowsSelectionImmediatelyOnTouchBegin">YES</bool>
+ <float key="IBUIRowHeight">44</float>
+ <float key="IBUISectionHeaderHeight">10</float>
+ <float key="IBUISectionFooterHeight">10</float>
+ </object>
+ </object>
+ <object class="IBObjectContainer" key="IBDocument.Objects">
+ <object class="NSMutableArray" key="connectionRecords">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">view</string>
+ <reference key="source" ref="372490531"/>
+ <reference key="destination" ref="873029372"/>
+ </object>
+ <int key="connectionID">5</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">dataSource</string>
+ <reference key="source" ref="873029372"/>
+ <reference key="destination" ref="372490531"/>
+ </object>
+ <int key="connectionID">6</int>
+ </object>
+ <object class="IBConnectionRecord">
+ <object class="IBCocoaTouchOutletConnection" key="connection">
+ <string key="label">delegate</string>
+ <reference key="source" ref="873029372"/>
+ <reference key="destination" ref="372490531"/>
+ </object>
+ <int key="connectionID">7</int>
+ </object>
+ </object>
+ <object class="IBMutableOrderedSet" key="objectRecords">
+ <object class="NSArray" key="orderedObjects">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="IBObjectRecord">
+ <int key="objectID">0</int>
+ <reference key="object" ref="0"/>
+ <reference key="children" ref="1000"/>
+ <nil key="parent"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-1</int>
+ <reference key="object" ref="372490531"/>
+ <reference key="parent" ref="0"/>
+ <string key="objectName">File's Owner</string>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">-2</int>
+ <reference key="object" ref="975951072"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ <object class="IBObjectRecord">
+ <int key="objectID">4</int>
+ <reference key="object" ref="873029372"/>
+ <reference key="parent" ref="0"/>
+ </object>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="flattenedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <object class="NSArray" key="dict.sortedKeys">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>-1.CustomClassName</string>
+ <string>-2.CustomClassName</string>
+ <string>4.IBEditorWindowLastContentRect</string>
+ <string>4.IBPluginDependency</string>
+ </object>
+ <object class="NSMutableArray" key="dict.values">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <string>FolderDetailViewController</string>
+ <string>UIResponder</string>
+ <string>{{329, 504}, {320, 480}}</string>
+ <string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
+ </object>
+ </object>
+ <object class="NSMutableDictionary" key="unlocalizedProperties">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <reference key="dict.values" ref="0"/>
+ </object>
+ <nil key="activeLocalization"/>
+ <object class="NSMutableDictionary" key="localizations">
+ <bool key="EncodedWithXMLCoder">YES</bool>
+ <reference key="dict.sortedKeys" ref="0"/>
+ <reference key="dict.values" ref="0"/>
+ </object>
+ <nil key="sourceID"/>
+ <int key="maxID">7</int>
+ </object>
+ <object class="IBClassDescriber" key="IBDocument.Classes"/>
+ <int key="IBDocument.localizationMode">0</int>
+ <string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>
+ <object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+ <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3</string>
+ <integer value="3000" key="NS.object.0"/>
+ </object>
+ <bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+ <int key="IBDocument.defaultPropertyAccessControl">3</int>
+ <string key="IBCocoaTouchPluginVersion">301</string>
+ </data>
+</archive>
#import "AddObjectViewController.h"
#import "OpenStackAppDelegate.h"
#import "RootViewController.h"
+#import "FolderDetailViewController.h"
@implementation FolderViewController
id item = [self.folder.sortedContents objectAtIndex:indexPath.row];
cell.textLabel.text = [item name];
- cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
if ([[item class] isEqual:[Folder class]]) {
-
+ if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
+ cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
+ } else {
+ cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
+ }
cell.imageView.image = [UIImage imageNamed:@"folder-icon.png"];
NSString *folderString = @"";
}
cell.detailTextLabel.text = [NSString stringWithFormat:@"%@%@", folderString, objectString];
} else if ([[item class] isEqual:[StorageObject class]]) {
+ cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
+
StorageObject *object = item;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
vc.parentFolderViewController = self;
[self.navigationController pushViewController:vc animated:YES];
[vc release];
+ if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
+ Folder *folderForDetailView;
+ if ([folder.sortedContents count] > 0) {
+ folderForDetailView = [self.folder.sortedContents objectAtIndex:indexPath.row];
+ }
+ FolderDetailViewController *folderDetailViewController = [[FolderDetailViewController alloc] initWithNibName:@"FolderDetailViewController" bundle:nil];
+ folderDetailViewController.account = account;
+ folderDetailViewController.container = container;
+ folderDetailViewController.folder = folderForDetailView;
+ [self presentPrimaryViewController:folderDetailViewController];
+ [folderDetailViewController release];
+ }
} else if ([[item class] isEqual:[StorageObject class]]) {
StorageObjectViewController *vc = [[StorageObjectViewController alloc] initWithNibName:@"StorageObjectViewController" bundle:nil];
vc.account = self.account;
}
}
+- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath {
+ Folder *folderForDetailView;
+ if ([folder.sortedContents count] > 0) {
+ folderForDetailView = [self.folder.sortedContents objectAtIndex:indexPath.row];
+ }
+ FolderDetailViewController *vc = [[FolderDetailViewController alloc] initWithNibName:@"FolderDetailViewController" bundle:nil];
+ vc.account = account;
+ vc.container = container;
+ vc.folder = folderForDetailView;
+
+ [self.navigationController pushViewController:vc animated:YES];
+ [vc release];
+}
+
#pragma mark -
#pragma mark Buttons
}
+ (OpenStackRequest *)writeObjectMetadataRequest:(OpenStackAccount *)account container:(Container *)container object:(StorageObject *)object {
- return nil;
+ NSString *fullPath = [NSString stringWithString:object.fullPath];
+ if ([fullPath length] && ([fullPath characterAtIndex:0] == '/'))
+ fullPath = [fullPath substringFromIndex:1];
+
+ NSString *metadataKeyHeaderPrefix;
+ if (![fullPath length])
+ metadataKeyHeaderPrefix = @"X-Container-Meta-";
+ else
+ metadataKeyHeaderPrefix = @"X-Object-Meta-";
+
+ OpenStackRequest *request = [OpenStackRequest filesRequest:account method:@"POST" path:[[NSString stringWithFormat:@"/%@/%@", container.name, fullPath] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
+
+ for (NSString *metadataKey in object.metadata) {
+ NSString *metadataKeyHeader = [NSString stringWithFormat:@"%@%@", metadataKeyHeaderPrefix, metadataKey];
+ [request.requestHeaders setObject:[object.metadata objectForKey:metadataKey] forKey:metadataKeyHeader];
+ }
+ return request;
}
+ (OpenStackRequest *)deleteObjectRequest:(OpenStackAccount *)account container:(Container *)container object:(StorageObject *)object {
object.contentType = [dict objectForKey:@"content_type"];
object.lastModified = [ComputeModel dateFromString:[dict objectForKey:@"last_modified"]];
+ object.metadata = [NSMutableDictionary dictionary];
+ for (NSString *key in dict) {
+ if ([key hasPrefix:@"x_object_meta_"]) {
+ NSString *metadataKey = [key substringFromIndex:14];
+ [object.metadata setObject:[dict objectForKey:key] forKey:metadataKey];
+ }
+ }
+
return object;
}
#import "FolderViewController.h"
#import "UIColor+MoreColors.h"
#import "OpenStackAppDelegate.h"
+#import "EditMetadataViewController.h"
#define kDetails 0
-#define kMetadata -1
+#define kMetadata 1
+
+#define maxMetadataViewableLength 12
+
// TODO: use etag to reset download
// TODO: try downloading directly to the file to save memory. don't use object.data
[super viewWillAppear:animated];
self.navigationItem.title = object.name;
+ NSIndexPath* selection = [self.tableView indexPathForSelectedRow];
+ if (selection)
+ [self.tableView deselectRowAtIndexPath:selection animated:YES];
+
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *shortPath = [NSString stringWithFormat:@"/%@/%@", self.container.name, self.object.fullPath];
[self setBackgroundView];
if (self.container.cdnEnabled) {
- cdnURLSection = 1;
- actionsSection = 2;
- deleteSection = 3;
+ cdnURLSection = 2;
+ actionsSection = 3;
+ deleteSection = 4;
} else {
cdnURLSection = -1;
- actionsSection = 1;
- deleteSection = 2;
+ actionsSection = 2;
+ deleteSection = 3;
}
// let's see if we can tweet
cdnURLActionSheet = [[UIActionSheet alloc] initWithTitle:[[NSString stringWithFormat:@"%@/%@", self.container.cdnURL, self.object.fullPath] stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding] delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:nil otherButtonTitles:@"Copy to Pasteboard", @"Open in Safari", @"Email Link to File", nil];
}
+ [self.tableView reloadData];
}
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
- return self.container.cdnEnabled ? 4 : 3;
+ return self.container.cdnEnabled ? 5 : 4;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
cell.detailTextLabel.text = @"";
} else {
NSString *key = [[object.metadata allKeys] objectAtIndex:indexPath.row];
- cell.textLabel.text = key;
- cell.detailTextLabel.text = [object.metadata objectForKey:key];
+ NSString *value = [object.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 == cdnURLSection) {
cell.detailTextLabel.textAlignment = UITextAlignmentLeft;
}
- (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
- if (indexPath.section == cdnURLSection) {
+ if (indexPath.section == kMetadata) {
+ EditMetadataViewController *vc = [[EditMetadataViewController alloc] initWithNibName:@"EditMetadataViewController" bundle:nil];
+ NSString *metadataKey;
+ NSString *metadataValue;
+
+ if (indexPath.row == [self.object.metadata count]) {
+ metadataKey = @"";
+ metadataValue = @"";
+ vc.deleteEnabled = FALSE;
+ vc.navigationItem.title = @"Add Metadata";
+ }
+ else {
+ metadataKey = [[self.object.metadata allKeys] objectAtIndex:indexPath.row];
+ metadataValue = [self.object.metadata objectForKey:metadataKey];
+ vc.deleteEnabled = YES;
+ vc.navigationItem.title = @"Edit Metadata";
+ }
+
+ vc.metadataKey = metadataKey;
+ vc.metadataValue = metadataValue;
+ vc.account = account;
+ vc.container = container;
+ vc.object = object;
+ [self.navigationController pushViewController:vc animated:YES];
+ [vc release];
+ } else if (indexPath.section == cdnURLSection) {
[cdnURLActionSheet showInView:self.view];
} else if (indexPath.section == actionsSection) {
if (indexPath.row == 0) {
/* Begin PBXBuildFile section */
1D3623260D0F684500981E51 /* OpenStackAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* OpenStackAppDelegate.m */; };
1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; };
+ 24A18E22143DB870003232F1 /* EditMetadataViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 24A18E20143DB870003232F1 /* EditMetadataViewController.m */; };
+ 24A18E23143DB870003232F1 /* EditMetadataViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 24A18E21143DB870003232F1 /* EditMetadataViewController.xib */; };
+ 24A18E56143F0429003232F1 /* FolderDetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 24A18E54143F0428003232F1 /* FolderDetailViewController.m */; };
+ 24A18E57143F0429003232F1 /* FolderDetailViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 24A18E55143F0428003232F1 /* FolderDetailViewController.xib */; };
+ 24E040051442FB3C0065E8DB /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 24E040041442FB3C0065E8DB /* libz.dylib */; };
2705F3EB12E7FA5900949131 /* RSTextFieldCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 2705F3E912E7FA5900949131 /* RSTextFieldCell.m */; };
2705F3ED12E7FA5900949131 /* RSTextFieldCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 2705F3E912E7FA5900949131 /* RSTextFieldCell.m */; };
270878F213282104006D4EE3 /* NSObject+NSCoding.m in Sources */ = {isa = PBXBuildFile; fileRef = 270878F013282104006D4EE3 /* NSObject+NSCoding.m */; };
277D9E7B126E78FD002C69D9 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27F740E6125FB44F002C6CB0 /* CFNetwork.framework */; };
277D9E7C126E78FD002C69D9 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27F740F9125FB46A002C6CB0 /* MobileCoreServices.framework */; };
277D9E7D126E78FD002C69D9 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27F740FD125FB476002C6CB0 /* SystemConfiguration.framework */; };
- 277D9E7E126E78FD002C69D9 /* libz.1.2.3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 27F74158125FB66F002C6CB0 /* libz.1.2.3.dylib */; };
277D9E7F126E78FD002C69D9 /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27869AF31263F22300CE3435 /* MessageUI.framework */; };
277D9E99126E7963002C69D9 /* MainWindow-Rackspace.xib in Resources */ = {isa = PBXBuildFile; fileRef = 277D9E98126E7963002C69D9 /* MainWindow-Rackspace.xib */; };
277D9EA2126E79A1002C69D9 /* AccountHomeViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2798AA45125E74F800E02475 /* AccountHomeViewController.xib */; };
27C15CAF13A7C4D500A1BB9F /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27F740E6125FB44F002C6CB0 /* CFNetwork.framework */; };
27C15CB013A7C4D800A1BB9F /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27F740F9125FB46A002C6CB0 /* MobileCoreServices.framework */; };
27C15CB113A7C4DB00A1BB9F /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27F740FD125FB476002C6CB0 /* SystemConfiguration.framework */; };
- 27C15CB213A7C4EA00A1BB9F /* libz.1.2.3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 27F74158125FB66F002C6CB0 /* libz.1.2.3.dylib */; };
27C15CB313A7C4EC00A1BB9F /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27869AF31263F22300CE3435 /* MessageUI.framework */; };
27C15CB413A7C4EF00A1BB9F /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27B0A1D81278047900A31CED /* QuartzCore.framework */; };
27C15CB613A7C50600A1BB9F /* libobjc.A.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 277F29211321A9DA001F8685 /* libobjc.A.dylib */; };
27F740E7125FB44F002C6CB0 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27F740E6125FB44F002C6CB0 /* CFNetwork.framework */; };
27F740FA125FB46A002C6CB0 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27F740F9125FB46A002C6CB0 /* MobileCoreServices.framework */; };
27F740FE125FB476002C6CB0 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 27F740FD125FB476002C6CB0 /* SystemConfiguration.framework */; };
- 27F74159125FB66F002C6CB0 /* libz.1.2.3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 27F74158125FB66F002C6CB0 /* libz.1.2.3.dylib */; };
27F7445C1261130F002C6CB0 /* UIViewController+Conveniences.m in Sources */ = {isa = PBXBuildFile; fileRef = 27F7445A1261130F002C6CB0 /* UIViewController+Conveniences.m */; };
27F7446312611341002C6CB0 /* NSObject+Conveniences.m in Sources */ = {isa = PBXBuildFile; fileRef = 27F7446112611341002C6CB0 /* NSObject+Conveniences.m */; };
27F744DA126122AF002C6CB0 /* NSString+Conveniences.m in Sources */ = {isa = PBXBuildFile; fileRef = 27F744D8126122AF002C6CB0 /* NSString+Conveniences.m */; };
1D3623240D0F684500981E51 /* OpenStackAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpenStackAppDelegate.h; sourceTree = "<group>"; };
1D3623250D0F684500981E51 /* OpenStackAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OpenStackAppDelegate.m; sourceTree = "<group>"; };
1D6058910D05DD3D006BFB54 /* OpenStack.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = OpenStack.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 24A18E1F143DB86F003232F1 /* EditMetadataViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EditMetadataViewController.h; sourceTree = "<group>"; };
+ 24A18E20143DB870003232F1 /* EditMetadataViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EditMetadataViewController.m; sourceTree = "<group>"; };
+ 24A18E21143DB870003232F1 /* EditMetadataViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = EditMetadataViewController.xib; sourceTree = "<group>"; };
+ 24A18E53143F0427003232F1 /* FolderDetailViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FolderDetailViewController.h; sourceTree = "<group>"; };
+ 24A18E54143F0428003232F1 /* FolderDetailViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FolderDetailViewController.m; sourceTree = "<group>"; };
+ 24A18E55143F0428003232F1 /* FolderDetailViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = FolderDetailViewController.xib; sourceTree = "<group>"; };
+ 24E040041442FB3C0065E8DB /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
2705F3E812E7FA5900949131 /* RSTextFieldCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RSTextFieldCell.h; sourceTree = "<group>"; };
2705F3E912E7FA5900949131 /* RSTextFieldCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RSTextFieldCell.m; sourceTree = "<group>"; };
270878EF13282104006D4EE3 /* NSObject+NSCoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+NSCoding.h"; sourceTree = "<group>"; };
271EFE59127E840900431D19 /* ChefAddServerPlugin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ChefAddServerPlugin.m; sourceTree = "<group>"; };
271EFE92127E884000431D19 /* AddServerPluginHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AddServerPluginHandler.h; sourceTree = "<group>"; };
271EFE93127E884000431D19 /* AddServerPluginHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AddServerPluginHandler.m; sourceTree = "<group>"; };
- 27265A191397EAE5000617C0 /* LBAlgorithmAnimationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.objj.h; path = LBAlgorithmAnimationViewController.h; sourceTree = "<group>"; };
+ 27265A191397EAE5000617C0 /* LBAlgorithmAnimationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LBAlgorithmAnimationViewController.h; sourceTree = "<group>"; };
27265A1A1397EAE5000617C0 /* LBAlgorithmAnimationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LBAlgorithmAnimationViewController.m; sourceTree = "<group>"; };
27265A1B1397EAE5000617C0 /* LBAlgorithmAnimationViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LBAlgorithmAnimationViewController.xib; sourceTree = "<group>"; };
27265ADF139802B6000617C0 /* lc-01_s01.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "lc-01_s01.png"; sourceTree = "<group>"; };
2726C63613B26D9F00BC7330 /* dot-orange@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "dot-orange@2x.png"; sourceTree = "<group>"; };
2726C63713B26D9F00BC7330 /* dot-blue@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "dot-blue@2x.png"; sourceTree = "<group>"; };
2726C63813B26D9F00BC7330 /* dot-green@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "dot-green@2x.png"; sourceTree = "<group>"; };
- 2726C64A13B28D1000BC7330 /* ConfigureLoadBalancerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.objj.h; path = ConfigureLoadBalancerViewController.h; sourceTree = "<group>"; };
+ 2726C64A13B28D1000BC7330 /* ConfigureLoadBalancerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConfigureLoadBalancerViewController.h; sourceTree = "<group>"; };
2726C64B13B28D1000BC7330 /* ConfigureLoadBalancerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ConfigureLoadBalancerViewController.m; sourceTree = "<group>"; };
272833A31270C87C00F8CCDD /* OpenStackViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpenStackViewController.h; sourceTree = "<group>"; };
272833A41270C87C00F8CCDD /* OpenStackViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OpenStackViewController.m; sourceTree = "<group>"; };
273FF39913313A5300437033 /* ServersOnHostViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ServersOnHostViewController.h; sourceTree = "<group>"; };
273FF39A13313A5300437033 /* ServersOnHostViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ServersOnHostViewController.m; sourceTree = "<group>"; };
273FF39B13313A5400437033 /* ServersOnHostViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ServersOnHostViewController.xib; sourceTree = "<group>"; };
- 2742A3EA13AFB24D00C10640 /* LBTitleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.objj.h; path = LBTitleView.h; sourceTree = "<group>"; };
+ 2742A3EA13AFB24D00C10640 /* LBTitleView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LBTitleView.h; sourceTree = "<group>"; };
2742A3EB13AFB24D00C10640 /* LBTitleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LBTitleView.m; sourceTree = "<group>"; };
2748C57C126E90FD00A24941 /* PingIPAddressViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PingIPAddressViewController.h; sourceTree = "<group>"; };
2748C57D126E90FD00A24941 /* PingIPAddressViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PingIPAddressViewController.m; sourceTree = "<group>"; };
2756082D136F3078009EB5BA /* LBVirtualIPTypeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LBVirtualIPTypeViewController.h; sourceTree = "<group>"; };
2756082E136F3078009EB5BA /* LBVirtualIPTypeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LBVirtualIPTypeViewController.m; sourceTree = "<group>"; };
2756082F136F3078009EB5BA /* LBVirtualIPTypeViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LBVirtualIPTypeViewController.xib; sourceTree = "<group>"; };
- 2758565F1399585000311115 /* LBLinkSharedVIPViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.objj.h; path = LBLinkSharedVIPViewController.h; sourceTree = "<group>"; };
+ 2758565F1399585000311115 /* LBLinkSharedVIPViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LBLinkSharedVIPViewController.h; sourceTree = "<group>"; };
275856601399585000311115 /* LBLinkSharedVIPViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LBLinkSharedVIPViewController.m; sourceTree = "<group>"; };
275856611399585000311115 /* LBLinkSharedVIPViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LBLinkSharedVIPViewController.xib; sourceTree = "<group>"; };
275B421112DBAE86003DF100 /* MainWindow-iPad.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "MainWindow-iPad.xib"; path = "Resources-iPad/MainWindow-iPad.xib"; sourceTree = "<group>"; };
27D5E222130F032400404EC2 /* LoadBalancersViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoadBalancersViewController.h; sourceTree = "<group>"; };
27D5E223130F032400404EC2 /* LoadBalancersViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LoadBalancersViewController.m; sourceTree = "<group>"; };
27D5E224130F032400404EC2 /* LoadBalancersViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = LoadBalancersViewController.xib; sourceTree = "<group>"; };
- 27DADC1213B94D6B00F9E906 /* LBNodeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.objj.h; path = LBNodeViewController.h; sourceTree = "<group>"; };
+ 27DADC1213B94D6B00F9E906 /* LBNodeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LBNodeViewController.h; sourceTree = "<group>"; };
27DADC1313B94D6B00F9E906 /* LBNodeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LBNodeViewController.m; sourceTree = "<group>"; };
- 27DC5DD513CB8F0F00091902 /* LoadBalancerConnectionThrottle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.objj.h; path = LoadBalancerConnectionThrottle.h; sourceTree = "<group>"; };
+ 27DC5DD513CB8F0F00091902 /* LoadBalancerConnectionThrottle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoadBalancerConnectionThrottle.h; sourceTree = "<group>"; };
27DC5DD613CB8F0F00091902 /* LoadBalancerConnectionThrottle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LoadBalancerConnectionThrottle.m; sourceTree = "<group>"; };
27E6B5D412D9211C00EA623F /* MediaViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediaViewController.h; sourceTree = "<group>"; };
27E6B5D512D9211C00EA623F /* MediaViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MediaViewController.m; sourceTree = "<group>"; };
27F740E6125FB44F002C6CB0 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; };
27F740F9125FB46A002C6CB0 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };
27F740FD125FB476002C6CB0 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
- 27F74158125FB66F002C6CB0 /* libz.1.2.3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.1.2.3.dylib; path = usr/lib/libz.1.2.3.dylib; sourceTree = SDKROOT; };
27F744591261130F002C6CB0 /* UIViewController+Conveniences.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIViewController+Conveniences.h"; sourceTree = "<group>"; };
27F7445A1261130F002C6CB0 /* UIViewController+Conveniences.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+Conveniences.m"; sourceTree = "<group>"; };
27F7446012611341002C6CB0 /* NSObject+Conveniences.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+Conveniences.h"; sourceTree = "<group>"; };
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ 24E040051442FB3C0065E8DB /* libz.dylib in Frameworks */,
7F8F374913859F190034710B /* libxml2.dylib in Frameworks */,
7F9351B913845AC80097720F /* libsqlite3.0.dylib in Frameworks */,
27F740B6125FB358002C6CB0 /* Foundation.framework in Frameworks */,
27F740E7125FB44F002C6CB0 /* CFNetwork.framework in Frameworks */,
27F740FA125FB46A002C6CB0 /* MobileCoreServices.framework in Frameworks */,
27F740FE125FB476002C6CB0 /* SystemConfiguration.framework in Frameworks */,
- 27F74159125FB66F002C6CB0 /* libz.1.2.3.dylib in Frameworks */,
27869AF41263F22300CE3435 /* MessageUI.framework in Frameworks */,
27B0A1D91278047900A31CED /* QuartzCore.framework in Frameworks */,
27C0510F12B00D3F00CB21C7 /* UIKit.framework in Frameworks */,
277D9E7B126E78FD002C69D9 /* CFNetwork.framework in Frameworks */,
277D9E7C126E78FD002C69D9 /* MobileCoreServices.framework in Frameworks */,
277D9E7D126E78FD002C69D9 /* SystemConfiguration.framework in Frameworks */,
- 277D9E7E126E78FD002C69D9 /* libz.1.2.3.dylib in Frameworks */,
277D9E7F126E78FD002C69D9 /* MessageUI.framework in Frameworks */,
271B09331279184D00525011 /* QuartzCore.framework in Frameworks */,
27F853EA12AEFAE4003327C0 /* UIKit.framework in Frameworks */,
27C15CAF13A7C4D500A1BB9F /* CFNetwork.framework in Frameworks */,
27C15CB013A7C4D800A1BB9F /* MobileCoreServices.framework in Frameworks */,
27C15CB113A7C4DB00A1BB9F /* SystemConfiguration.framework in Frameworks */,
- 27C15CB213A7C4EA00A1BB9F /* libz.1.2.3.dylib in Frameworks */,
27C15CB313A7C4EC00A1BB9F /* MessageUI.framework in Frameworks */,
27C15CB413A7C4EF00A1BB9F /* QuartzCore.framework in Frameworks */,
27C15CB613A7C50600A1BB9F /* libobjc.A.dylib in Frameworks */,
27F852F112AEF6AB003327C0 /* ContainersViewController.xib */,
27C0517512B0134F00CB21C7 /* AddContainerViewController.h */,
27C0517612B0134F00CB21C7 /* AddContainerViewController.m */,
+ 27C0517712B0134F00CB21C7 /* AddContainerViewController.xib */,
277B89B212B97D6D006483B0 /* FolderViewController.h */,
277B89B312B97D6D006483B0 /* FolderViewController.m */,
277B89B412B97D6D006483B0 /* FolderViewController.xib */,
278906DB12BEDAB5007112B6 /* StorageObjectViewController.h */,
278907A112BEF72C007112B6 /* StorageObjectViewController.m */,
278906DD12BEDAB5007112B6 /* StorageObjectViewController.xib */,
+ 24A18E1F143DB86F003232F1 /* EditMetadataViewController.h */,
+ 24A18E20143DB870003232F1 /* EditMetadataViewController.m */,
+ 24A18E21143DB870003232F1 /* EditMetadataViewController.xib */,
27E6B5D412D9211C00EA623F /* MediaViewController.h */,
27E6B5D512D9211C00EA623F /* MediaViewController.m */,
27E6B5D612D9211C00EA623F /* MediaViewController.xib */,
+ 24A18E53143F0427003232F1 /* FolderDetailViewController.h */,
+ 24A18E54143F0428003232F1 /* FolderDetailViewController.m */,
+ 24A18E55143F0428003232F1 /* FolderDetailViewController.xib */,
2788941712C28C66006448E2 /* ContainerDetailViewController.h */,
2788941812C28C66006448E2 /* ContainerDetailViewController.m */,
2788941912C28C66006448E2 /* ContainerDetailViewController.xib */,
- 27C0517712B0134F00CB21C7 /* AddContainerViewController.xib */,
);
name = "Object Storage";
sourceTree = "<group>";
27F740E6125FB44F002C6CB0 /* CFNetwork.framework */,
27F740F9125FB46A002C6CB0 /* MobileCoreServices.framework */,
27F740FD125FB476002C6CB0 /* SystemConfiguration.framework */,
- 27F74158125FB66F002C6CB0 /* libz.1.2.3.dylib */,
+ 24E040041442FB3C0065E8DB /* libz.dylib */,
27869AF31263F22300CE3435 /* MessageUI.framework */,
27B0A1D81278047900A31CED /* QuartzCore.framework */,
27F853E912AEFAE4003327C0 /* UIKit.framework */,
27295C1313C6563200A32F20 /* dark-grey-highlight.png in Resources */,
27C38BC013D0D48500CC7222 /* red-delete-button@2x.png in Resources */,
27C38BC213D0D48500CC7222 /* red-delete-button.png in Resources */,
+ 24A18E23143DB870003232F1 /* EditMetadataViewController.xib in Resources */,
+ 24A18E57143F0429003232F1 /* FolderDetailViewController.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
2726C64E13B28D1000BC7330 /* ConfigureLoadBalancerViewController.m in Sources */,
27DADC1613B94D6C00F9E906 /* LBNodeViewController.m in Sources */,
27DC5DD813CB8F0F00091902 /* LoadBalancerConnectionThrottle.m in Sources */,
+ 24A18E22143DB870003232F1 /* EditMetadataViewController.m in Sources */,
+ 24A18E56143F0429003232F1 /* FolderDetailViewController.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};