Statistics
| Branch: | Tag: | Revision:

root / Classes / EditMetadataViewController.m @ 3a8071d4

History | View | Annotate | Download (15.2 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
    [activityIndicatorView release];
73
    [super dealloc];
74
}
75

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

    
84
#pragma mark - View lifecycle
85

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

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

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

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

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

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

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

    
120
#pragma mark - Table view data source
121

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

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

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

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

    
188

    
189
#pragma mark - Table view delegate
190

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

    
194
    
195
    if (indexPath.section != kMetadata)
196
        [self.view endEditing:YES];
197
    
198
    NSString *activityMessage;
199
    NSIndexPath *keyCellIndexPath;
200
    NSIndexPath *valueCellIndexPath;
201
    UITableViewCell *cell;
202
    
203
    switch (indexPath.section) {
204
        case kSaveMedata:
205
            keyCellIndexPath = [NSIndexPath indexPathForRow:0 inSection:kMetadata];
206
            cell = [self.tableView cellForRowAtIndexPath:keyCellIndexPath];
207
            UITextField *textField = [[cell.contentView subviews] objectAtIndex:0];
208
            self.userInputMetaKey = textField.text;
209
        
210
            if ([userInputMetaKey length] == 0
211
                || [[userInputMetaKey stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0) {
212
                [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
213
                [self alert:@"Invalid input" message:@"Metadata key cannot be empty"];
214
                return;
215
            }
216
            
217
            valueCellIndexPath = [NSIndexPath indexPathForRow:1 inSection:kMetadata];
218
            cell = [self.tableView cellForRowAtIndexPath:valueCellIndexPath];
219
            textField = [[cell.contentView subviews] objectAtIndex:0];
220
            self.userInputMetaValue = textField.text;
221
            [object.metadata removeObjectForKey:metadataKey];
222
            [object.metadata setObject:userInputMetaValue forKey:userInputMetaKey];
223
            
224
            if (objectIsFolder && ![PithosUtilities isContentTypeDirectory:object.contentType]) {
225
                if (((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) &&
226
                     [folderViewController.parentFolderViewController.folder.objects objectForKey:object.name]) || 
227
                    ((UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad) &&
228
                     [folderViewController.folder.objects objectForKey:object.name])) {
229
                    NSString *alertMessage = [NSString stringWithFormat:@"In order to apply the changes in '%@', the object at the same path must be replaced. Continue?",object.name];
230
                    NSString *alertTitle = @"Apply changes";
231
                    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:alertTitle
232
                                                                    message:alertMessage
233
                                                                   delegate:self
234
                                                          cancelButtonTitle:@"Cancel"
235
                                                          otherButtonTitles:@"OK", nil];
236
                    [alert show];
237
                    [alert release];
238
                    return;
239
                } else {
240
                    activityMessage = @"Saving metadata...";
241
                    [activityIndicatorView release];
242
                    activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage];
243
                    [activityIndicatorView addToView:self.view];
244
                    
245
                    object.name = object.fullPath;
246
                    object.contentType = @"application/directory";
247
                    object.data = [NSData data];
248
                    [self createNewFolder];
249
                    return;
250
                }
251
            }
252
            
253
            activityMessage = @"Saving metadata";
254
            [activityIndicatorView release];
255
            activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage];
256
            [activityIndicatorView addToView:self.view];
257
            [[self.account.manager writeObjectMetadata:container object:object] 
258
             success:^(OpenStackRequest *request) {
259
                 self.metadataKey = userInputMetaKey;
260
                 self.metadataValue = userInputMetaValue;
261
                 removeMetadataEnabled = YES;
262
                 [self.tableView reloadData];
263
                 [activityIndicatorView removeFromSuperview];
264
                 [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
265
                 if (objectIsContainer) {
266
                     container.metadata = object.metadata;
267
                     [self.account.containers setObject:container forKey:container.name];
268
                 }
269
             }
270
             failure:^(OpenStackRequest *request) { 
271
                 [object.metadata removeObjectForKey:userInputMetaKey];
272
                 [object.metadata setObject:metadataValue forKey:metadataKey];
273
                 [activityIndicatorView removeFromSuperview];
274
                 [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
275
                 [self alert:@"There was a problem saving the metadata." request:request];
276
             }];
277
                        
278
            break;
279
        case kDeleteMetadata:
280
            activityMessage = @"Deleting metadata";
281
            [activityIndicatorView release];
282
            activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage];
283
            [activityIndicatorView addToView:self.view];
284

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

    
305
             }];
306
            break;
307
    }
308
}
309

    
310
#pragma mark - Alertview delegate
311

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

    
329
#pragma mark - Textfield delegate
330

    
331

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

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

    
354
#pragma mark - add observers
355

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

    
390
@end