Statistics
| Branch: | Tag: | Revision:

root / Classes / EditMetadataViewController.m @ 54fd5c36

History | View | Annotate | Download (15 kB)

1
//
2
//  EditMetadataViewController.m
3
//  pithos-ios
4
//
5
// Copyright 2011 GRNET S.A. All rights reserved.
6
//
7
// Redistribution and use in source and binary forms, with or
8
// without modification, are permitted provided that the following
9
// conditions are met:
10
// 
11
//   1. Redistributions of source code must retain the above
12
//      copyright notice, this list of conditions and the following
13
//      disclaimer.
14
// 
15
//   2. Redistributions in binary form must reproduce the above
16
//      copyright notice, this list of conditions and the following
17
//      disclaimer in the documentation and/or other materials
18
//      provided with the distribution.
19
// 
20
// THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
21
// OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
24
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
27
// USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28
// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31
// POSSIBILITY OF SUCH DAMAGE.
32
// 
33
// The views and conclusions contained in the software and
34
// documentation are those of the authors and should not be
35
// interpreted as representing official policies, either expressed
36
// or implied, of GRNET S.A.
37

    
38
#import "EditMetadataViewController.h"
39
#import "AccountManager.h"
40
#import "UIViewController+Conveniences.h"
41
#import "FolderViewController.h"
42
#import "Folder.h"
43
#import "PithosUtilities.h"
44
#import "APICallback.h"
45

    
46

    
47

    
48
@implementation EditMetadataViewController
49

    
50

    
51
@synthesize container, account, object;
52

    
53
@synthesize metadataKey;
54
@synthesize metadataValue;
55
@synthesize userInputMetaKey, userInputMetaValue;
56
@synthesize removeMetadataEnabled, objectIsFolder, folderViewController, objectIsContainer;
57

    
58
#define kMetadata 0 
59
#define kSaveMedata 1
60
#define kDeleteMetadata 2
61

    
62

    
63
- (void)dealloc
64
{
65
    [account release];
66
    [container release];
67
    [object release];
68
    [metadataKey release];
69
    [metadataValue release];
70
    [userInputMetaKey release];
71
    [userInputMetaValue release];
72
    [super dealloc];
73
}
74

    
75
- (void)didReceiveMemoryWarning
76
{
77
    // Releases the view if it doesn't have a superview.
78
    [super didReceiveMemoryWarning];
79
    
80
    // Release any cached data, images, etc that aren't in use.
81
}
82

    
83
#pragma mark - View lifecycle
84

    
85
- (void)viewDidLoad
86
{
87
    [super viewDidLoad];
88
}
89

    
90
- (void)viewDidUnload
91
{
92
    [super viewDidUnload];
93
}
94

    
95
- (void)viewWillAppear:(BOOL)animated
96
{    
97
    [super viewWillAppear:animated];
98
}
99

    
100
- (void)viewDidAppear:(BOOL)animated
101
{
102
    [super viewDidAppear:animated];
103
}
104

    
105
- (void)viewWillDisappear:(BOOL)animated
106
{
107
    [super viewWillDisappear:animated];
108
}
109

    
110
- (void)viewDidDisappear:(BOOL)animated
111
{
112
    [super viewDidDisappear:animated];
113
}
114

    
115
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
116
    return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait);
117
}
118

    
119
#pragma mark - Table view data source
120

    
121
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
122
{
123
    return (removeMetadataEnabled)? 3:2;
124
}
125

    
126
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
127
{
128
    if (section == kMetadata)
129
        return 2;
130
    else
131
        return 1;
132
}
133

    
134
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
135
{
136
    static NSString *CellIdentifier = @"Cell";
137
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
138
    if (cell == nil) {
139
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
140
    }
141
                
142
    if (indexPath.section == kMetadata) {
143
        UITextField *textField = nil;
144
        for (id subView in cell.contentView.subviews) {
145
            if ([subView isKindOfClass:[UITextField class]]) {
146
                textField = (UITextField *)subView;
147
            }
148
        }
149
        
150
        if (textField == nil) {
151
            CGRect bounds = [cell.contentView bounds];
152
            CGRect rect = CGRectInset(bounds, 10.0, 10.0);                        
153
            textField = [[UITextField alloc] initWithFrame:rect];
154
            [textField setFrame:rect];
155
        }
156
        [textField setClearButtonMode:UITextFieldViewModeWhileEditing];
157
        [textField setBackgroundColor:[UIColor clearColor]];
158
        [textField setOpaque:YES];
159
        [textField setAutocorrectionType:UITextAutocorrectionTypeNo];
160
        [textField setAutocapitalizationType:UITextAutocapitalizationTypeNone];
161
        [textField setDelegate:self];
162
        textField.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
163

    
164
        if (indexPath.row == 0) {
165
            [textField setReturnKeyType:UIReturnKeyNext];
166
            textField.placeholder = @"Key";
167
            textField.text = self.metadataKey;
168
            textField.tag = 0;
169
        }
170
        else if (indexPath.row == 1) {
171
            textField.placeholder = @"Value";
172
            textField.text = self.metadataValue;
173
            textField.tag = 1;
174
        }
175
            
176
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
177
        [cell.contentView addSubview:textField];
178
    }
179
    else if (indexPath.section == kSaveMedata) 
180
        cell.textLabel.text = @"Save";
181
    else if (indexPath.section == kDeleteMetadata)
182
        cell.textLabel.text = @"Remove";
183
    
184
    return cell;
185
}
186

    
187

    
188
#pragma mark - Table view delegate
189

    
190
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
191
{
192

    
193
    
194
    if (indexPath.section != kMetadata)
195
        [self.view endEditing:YES];
196
    
197
    NSString *activityMessage;
198
    NSIndexPath *keyCellIndexPath;
199
    NSIndexPath *valueCellIndexPath;
200
    UITableViewCell *cell;
201
    
202
    switch (indexPath.section) {
203
        case kSaveMedata:
204
            keyCellIndexPath = [NSIndexPath indexPathForRow:0 inSection:kMetadata];
205
            cell = [self.tableView cellForRowAtIndexPath:keyCellIndexPath];
206
            UITextField *textField = [[cell.contentView subviews] objectAtIndex:0];
207
            self.userInputMetaKey = textField.text;
208
        
209
            if ([userInputMetaKey length] == 0
210
                || [[userInputMetaKey stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0) {
211
                [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
212
                [self alert:@"Invalid input" message:@"Metadata key cannot be empty"];
213
                return;
214
            }
215
            
216
            valueCellIndexPath = [NSIndexPath indexPathForRow:1 inSection:kMetadata];
217
            cell = [self.tableView cellForRowAtIndexPath:valueCellIndexPath];
218
            textField = [[cell.contentView subviews] objectAtIndex:0];
219
            self.userInputMetaValue = textField.text;
220
            [object.metadata removeObjectForKey:metadataKey];
221
            [object.metadata setObject:userInputMetaValue forKey:userInputMetaKey];
222
            
223
            if (objectIsFolder && ![PithosUtilities isContentTypeDirectory:object.contentType]) {
224
                if (((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) &&
225
                     [folderViewController.parentFolderViewController.folder.objects objectForKey:object.name]) || 
226
                    ((UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad) &&
227
                     [folderViewController.folder.objects objectForKey:object.name])) {
228
                    NSString *alertMessage = [NSString stringWithFormat:@"In order to apply the changes in '%@', the object at the same path must be replaced. Continue?",object.name];
229
                    NSString *alertTitle = @"Apply changes";
230
                    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:alertTitle
231
                                                                    message:alertMessage
232
                                                                   delegate:self
233
                                                          cancelButtonTitle:@"Cancel"
234
                                                          otherButtonTitles:@"OK", nil];
235
                    [alert show];
236
                    return;
237
                } else {
238
                    activityMessage = @"Saving metadata...";
239
                    activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage];
240
                    [activityIndicatorView addToView:self.view];
241
                    
242
                    object.name = object.fullPath;
243
                    object.contentType = @"application/directory";
244
                    object.data = [NSData data];
245
                    [self createNewFolder];
246
                    return;
247
                }
248
            }
249
            
250
            activityMessage = @"Saving metadata";
251
            activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage];
252
            [activityIndicatorView addToView:self.view];
253

    
254
            [[self.account.manager writeObjectMetadata:container object:object] 
255
             success:^(OpenStackRequest *request) {
256
                 self.metadataKey = userInputMetaKey;
257
                 self.metadataValue = userInputMetaValue;
258
                 removeMetadataEnabled = YES;
259
                 [self.tableView reloadData];
260
                 [activityIndicatorView removeFromSuperviewAndRelease];
261
                 [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
262
                 if (objectIsContainer) {
263
                     container.metadata = object.metadata;
264
                     [self.account.containers setObject:container forKey:container.name];
265
                 }
266
             }
267
             failure:^(OpenStackRequest *request) { 
268
                 [object.metadata removeObjectForKey:userInputMetaKey];
269
                 [object.metadata setObject:metadataValue forKey:metadataKey];
270
                 [activityIndicatorView removeFromSuperviewAndRelease];
271
                 [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
272
                 [self alert:@"There was a problem saving the metadata." request:request];
273
             }];
274
                        
275
            break;
276
        case kDeleteMetadata:
277
            activityMessage = @"Deleting metadata";
278
            activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage];
279
            [activityIndicatorView addToView:self.view];
280

    
281
            [object.metadata removeObjectForKey:metadataKey];
282
            [[self.account.manager writeObjectMetadata:container object:object] 
283
             success:^(OpenStackRequest *request) {
284
                 [activityIndicatorView removeFromSuperviewAndRelease];
285
                 [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
286
                 self.metadataKey = @"";
287
                 self.metadataValue = @"";
288
                 removeMetadataEnabled = NO;
289
                 [self.tableView reloadData];
290
                 if (objectIsContainer) {
291
                     container.metadata = object.metadata;
292
                     [self.account.containers setObject:container forKey:container.name];
293
                 }
294
             }
295
             failure:^(OpenStackRequest *request) {
296
                 [object.metadata setObject:metadataValue forKey:metadataKey];
297
                 [activityIndicatorView removeFromSuperviewAndRelease];
298
                 [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
299
                 [self alert:@"There was a problem saving the metadata." request:request];
300

    
301
             }];
302
            break;
303
    }
304
}
305

    
306
#pragma mark - Alertview delegate
307

    
308
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
309
{
310
    if (buttonIndex == 1) {
311
        NSString *activityMessage = @"Applying permissions...";
312
        
313
        activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage];
314
        [activityIndicatorView addToView:self.view];
315
        
316
        object.name = object.fullPath;
317
        object.contentType = @"application/directory";
318
        object.data = [NSData data];
319
        [self createNewFolder];      
320
    } else {
321
        [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
322
    }
323
}
324

    
325
#pragma mark - Textfield delegate
326

    
327

    
328
- (BOOL)textFieldShouldReturn:(UITextField *)textField
329
{
330
    
331
    if ([textField returnKeyType] == UIReturnKeyNext)
332
    {
333
        if ([textField.text length] == 0
334
            || [[textField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0) {
335
            [self alert:@"Invalid input" message:@"Metadata key cannot be empty"];
336
        }
337

    
338
        NSInteger nextTag = [textField tag] + 1;
339
        UIView *nextTextField = [self.tableView viewWithTag:nextTag];
340
        [nextTextField becomeFirstResponder];
341
    }
342
    else
343
    {
344
        [textField resignFirstResponder];
345
    }
346
    
347
    return YES;
348
}
349

    
350
#pragma mark - add observers
351

    
352
- (void)createNewFolder {
353
    [[self.account.manager writeObject:container object:object downloadProgressDelegate:nil] 
354
     success:^(OpenStackRequest *request) {
355
         Folder *newFolder = [[Folder alloc] init];
356
         newFolder.name = [[object.name componentsSeparatedByString:@"/"] lastObject];
357
         newFolder.parent = folderViewController.folder;
358
         newFolder.sharing = folderViewController.folder.sharing;
359
         newFolder.metadata = object.metadata;
360
         [folderViewController.folder.folders setObject:newFolder forKey:newFolder.name];
361
         [activityIndicatorView removeFromSuperviewAndRelease];
362
         [newFolder release];
363
         self.metadataKey = userInputMetaKey;
364
         self.metadataValue = userInputMetaValue;
365
         removeMetadataEnabled = YES;
366
         [self.tableView reloadData];
367
         [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
368
         if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
369
             [self.folderViewController refreshButtonPressed:nil];
370
         }
371
         else {
372
             self.folderViewController.needsRefreshing = YES;
373
             self.folderViewController.refreshWhenAppeared = YES;
374
         }
375
     }
376
     failure:^(OpenStackRequest *request) {
377
         [object.metadata removeObjectForKey:userInputMetaKey];
378
         [object.metadata setObject:metadataValue forKey:metadataKey];
379
         [activityIndicatorView removeFromSuperviewAndRelease];
380
         [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
381
         [self.tableView reloadData];
382
         [self alert:@"There was a problem saving the metadata." request:request];
383
     }];
384
}
385

    
386
@end